diff --git a/NuGet.config b/NuGet.config index 61fbae97a783c..26a2f6f90d445 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,8 @@ + + diff --git a/azure-pipelines-integration-corehost.yml b/azure-pipelines-integration-corehost.yml index 62648c365e7b9..09b7766625b0a 100644 --- a/azure-pipelines-integration-corehost.yml +++ b/azure-pipelines-integration-corehost.yml @@ -59,7 +59,7 @@ parameters: - name: queueName displayName: Queue Name type: string - default: windows.vs2022preview.amd64.open + default: windows.vs2022preview.scout.amd64.open values: - windows.vs2022.amd64.open - windows.vs2022.scout.amd64.open diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml index a7d5aaefe8eea..60ee9b5a40e61 100644 --- a/azure-pipelines-integration.yml +++ b/azure-pipelines-integration.yml @@ -56,7 +56,7 @@ parameters: - name: queueName displayName: Queue Name type: string - default: windows.vs2022preview.amd64.open + default: windows.vs2022preview.scout.amd64.open values: - windows.vs2022.amd64.open - windows.vs2022.scout.amd64.open diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ff0bfd6c1f468..b691df4dfa0b7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -425,7 +425,10 @@ stages: steps: - template: eng/pipelines/checkout-windows-task.yml - - script: eng/test-determinism.cmd -configuration Debug + - script: eng/make-bootstrap.cmd -name determinism + displayName: Build Bootstrap Compiler + + - script: eng/test-determinism.cmd -configuration Debug -bootstrapDir $(Build.SourcesDirectory)/artifacts/bootstrap/determinism displayName: Build - Validate determinism - template: eng/pipelines/publish-logs.yml @@ -445,12 +448,11 @@ stages: steps: - template: eng/pipelines/build-bootstrap.yml parameters: - bootstrapName: Default - bootstrapToolset: AnyCpu + toolset: Default - job: Correctness_Bootstrap_Build_Framework dependsOn: Determine_Changes - condition: ne(variables['Build.Reason'], 'Pull Request') + condition: ne(variables['Build.Reason'], 'PullRequest') pool: ${{ parameters.vs2022PreviewPool }} timeoutInMinutes: 90 variables: @@ -460,8 +462,7 @@ stages: steps: - template: eng/pipelines/build-bootstrap.yml parameters: - bootstrapName: Framework - bootstrapToolset: Framework + toolset: Framework - job: Correctness_TodoCheck pool: ${{ parameters.ubuntuPool }} @@ -484,7 +485,7 @@ stages: steps: - template: eng/pipelines/checkout-windows-task.yml - - powershell: .\eng\test-rebuild.ps1 -ci -configuration Release + - script: .\eng\test-rebuild.cmd -ci -configuration Release -bootstrap displayName: Run BuildValidator - task: PublishBuildArtifacts@1 diff --git a/docs/Language Feature Status.md b/docs/Language Feature Status.md index 55277310a87d5..4d4c5f1309032 100644 --- a/docs/Language Feature Status.md +++ b/docs/Language Feature Status.md @@ -17,7 +17,7 @@ efforts behind them. | [Roles/Extensions](https://github.com/dotnet/csharplang/issues/5497) | [roles](https://github.com/dotnet/roslyn/tree/features/roles) | [In Progress](https://github.com/dotnet/roslyn/issues/66722) | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [jjonescz](https://github.com/jjonescz) | | [MadsTorgersen](https://github.com/MadsTorgersen) | | [Escape character](https://github.com/dotnet/csharplang/issues/7400) | N/A | [In Progress](https://github.com/dotnet/roslyn/pull/70497) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [jcouv](https://github.com/jcouv), [RikkiGibson](https://github.com/RikkiGibson) | | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | | [Method group natural type improvements](https://github.com/dotnet/csharplang/blob/main/proposals/method-group-natural-type-improvements.md) | main | In Progress | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [cston](https://github.com/cston) | | [jcouv](https://github.com/jcouv) | -| [Native lock](https://github.com/dotnet/csharplang/issues/7104) | main | [In Progress](https://github.com/dotnet/roslyn/pull/71716) | [jjonescz](https://github.com/jjonescz) | [cston](https://github.com/cston), [RikkiGibson](https://github.com/RikkiGibson) | | [stephentoub](https://github.com/stephentoub) | +| [`Lock` object](https://github.com/dotnet/csharplang/issues/7104) | [LockObject](https://github.com/dotnet/roslyn/tree/features/LockObject) | [In Progress](https://github.com/dotnet/roslyn/issues/71888) | [jjonescz](https://github.com/jjonescz) | [cston](https://github.com/cston), [RikkiGibson](https://github.com/RikkiGibson) | | [stephentoub](https://github.com/stephentoub) | | Implicit indexer access in object initializers | main | [Merged into 17.9p3](https://github.com/dotnet/roslyn/pull/70649) | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [cston](https://github.com/cston) | | | # C# 12.0 diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md index 2d960d3a31cc8..6bca00047ff0e 100644 --- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md +++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 8.md @@ -1,5 +1,33 @@ # This document lists known breaking changes in Roslyn after .NET 7 all the way to .NET 8. +## Ref modifiers of dynamic arguments should be compatible with ref modifiers of corresponding parameters + +***Introduced in Visual Studio 2022 version 17.10*** + +Ref modifiers of dynamic arguments should be compatible with ref modifiers of corresponding parameters +at compile time. This can cause an overload resolution involving dynamic arguments to fail at compile time +instead of runtime. + +Previously, a mismatch was allowed at compile time, delaying the overload resolution failure to +runtime. + +For example, the following code used to compile without an error, but was failing with +exception: "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'C.f(ref object)' has some invalid arguments" +It is going to produce a compilation error now. +```csharp +public class C +{ + public void f(ref dynamic a) + { + } + + public void M(dynamic d) + { + f(d); // error CS1620: Argument 1 must be passed with the 'ref' keyword + } +} +``` + ## Collection expression target type must have constructor and `Add` method ***Introduced in Visual Studio 2022 version 17.10*** diff --git a/docs/contributing/Target Framework Strategy.md b/docs/contributing/Target Framework Strategy.md index 28fdfa9034cc2..be6de4f06a091 100644 --- a/docs/contributing/Target Framework Strategy.md +++ b/docs/contributing/Target Framework Strategy.md @@ -9,6 +9,7 @@ The roslyn repository produces components for a number of different products tha - Source build: requires us to ship `$(NetCurrent)` and `$(NetPrevious)` in workspaces and below (presently `net9.0` and `net8.0` respectively) - Visual Studio: requires us to ship `net472` for base IDE components and `$(NetVisualStudio)` (presently `net8.0`) for private runtime components. - Visual Studio Code: expects us to ship against the same runtime as DevKit (presently `net7.0`) to avoid two runtime downloads. +- MSBuildWorkspace: requires to ship a process that must be usable on the lowest supported SDK (presently `net6.0`) It is not reasonable for us to take the union of all TFM and multi-target every single project to them. That would add several hundred compilations to any build operation which would in turn negatively impact our developer throughput. Instead we attempt to use the TFM where needed. That keeps our builds smaller but increases complexity a bit as we end up shipping a mix of TFM for binaries across our layers. @@ -22,7 +23,8 @@ Projects in our repository should include the following values in `` setting. Instead our repo uses the above values and when inside source build or VMR our properties are initialized with arcade properties. diff --git a/eng/Directory.Packages.props b/eng/Directory.Packages.props index 49877e81eb5f1..f5de301ea0523 100644 --- a/eng/Directory.Packages.props +++ b/eng/Directory.Packages.props @@ -1,7 +1,7 @@ - 3.11.0-beta1.23364.2 + 3.11.0-beta1.24081.1 8.0.0-preview.23468.1 1.1.2-beta1.23411.1 0.1.187-beta @@ -21,10 +21,13 @@ 8.0.0 2.4.1 2.1.0 + 17.9.43-preview-1 @@ -32,14 +35,14 @@ - - + + - + @@ -54,8 +57,9 @@ - - + + + @@ -104,7 +108,7 @@ - + @@ -150,26 +154,26 @@ packages we will keep it untied to the RoslynDiagnosticsNugetPackageVersion we use for other analyzers to ensure it stays on a release version. --> - - + + - + - + - + - - - - + + + + @@ -177,12 +181,12 @@ - + - + - + @@ -205,7 +209,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c60350d09b98d..6599813ffbb62 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,20 +1,23 @@ - + + https://github.com/dotnet/source-build-externals - e844aa02a05b90d8cbe499676ec6ee0f19ec4980 + f1ef074dfcf79d2f2da6e6ff9df8696a32aa063c - + + https://github.com/dotnet/source-build-reference-packages - 412264fd6c04712d1d31ff05d37c6919101ef4f4 + ffac2194c39660f03761ba81bdd6026202942184 https://github.com/dotnet/command-line-api a045dd54a4c44723c215d992288160eb1401bb7f + https://github.com/dotnet/command-line-api a045dd54a4c44723c215d992288160eb1401bb7f @@ -25,6 +28,14 @@ https://github.com/dotnet/runtime d099f075e45d2aa6007a22b71b45a08758559f80 + + https://github.com/dotnet/runtime + d099f075e45d2aa6007a22b71b45a08758559f80 + + + https://github.com/dotnet/runtime + d099f075e45d2aa6007a22b71b45a08758559f80 + https://github.com/dotnet/runtime d099f075e45d2aa6007a22b71b45a08758559f80 @@ -54,17 +65,28 @@ https://github.com/dotnet/arcade 61ae141d2bf3534619265c8f691fd55dc3e75147 + + + + https://github.com/dotnet/arcade + 61ae141d2bf3534619265c8f691fd55dc3e75147 https://github.com/dotnet/xliff-tasks 73f0850939d96131c28cf6ea6ee5aacb4da0083a + + + + https://github.com/dotnet/xliff-tasks + 73f0850939d96131c28cf6ea6ee5aacb4da0083a https://github.com/dotnet/symreader 27e584661980ee6d82c419a2a471ae505b7d122e + https://github.com/dotnet/symreader 27e584661980ee6d82c419a2a471ae505b7d122e diff --git a/eng/Versions.props b/eng/Versions.props index 681a8d72b9d4f..76efac949adbb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -8,7 +8,7 @@ 4 10 0 - 1 + 2 $(MajorVersion).$(MinorVersion).$(PatchVersion) 7.0.3 + 7.0.0 3.3.4 3.3.0 8.0.0-preview.23468.1 2.0.0 + 7.0.0 7.0.0 7.0.0 7.0.0 4.10.0-1.24061.4 17.9.3137-preview3 2.4.1 + 1.0.803 + 13.0.3 + + 9.0.0-beta.24076.5 true diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index f4037b71b35f1..642ceadf7a8bc 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -12,8 +12,6 @@ $PublishDataUrl = "https://raw.githubusercontent.com/dotnet/roslyn/main/eng/conf $binaryLog = if (Test-Path variable:binaryLog) { $binaryLog } else { $false } $nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { $false } -$bootstrapDir = if (Test-Path variable:bootstrapDir) { $bootstrapDir } else { "" } -$bootstrapConfiguration = if (Test-Path variable:bootstrapConfiguration) { $bootstrapConfiguration } else { "Release" } $properties = if (Test-Path variable:properties) { $properties } else { @() } $originalTemp = $env:TEMP; @@ -89,7 +87,11 @@ function Exec-Block([scriptblock]$cmd) { } } -function Exec-CommandCore([string]$command, [string]$commandArgs, [switch]$useConsole = $true) { +function Exec-CommandCore([string]$command, [string]$commandArgs, [switch]$useConsole = $true, [switch]$echoCommand = $true) { + if ($echoCommand) { + Write-Host "$command $commandArgs" + } + if ($useConsole) { $exitCode = Exec-Process $command $commandArgs if ($exitCode -ne 0) { @@ -151,27 +153,39 @@ function Exec-CommandCore([string]$command, [string]$commandArgs, [switch]$useCo # $args = "/p:ManualBuild=true Test.proj" # Exec-Command $msbuild $args # -function Exec-Command([string]$command, [string]$commandArgs) { - Exec-CommandCore -command $command -commandArgs $commandargs -useConsole:$false -} - -# Functions exactly like Exec-Command but lets the process re-use the current -# console. This means items like colored output will function correctly. -# -# In general this command should be used in place of -# Exec-Command $msbuild $args | Out-Host -# -function Exec-Console([string]$command, [string]$commandArgs) { - Exec-CommandCore -command $command -commandArgs $commandargs -useConsole:$true +# The -useConsole argument controls if the process should re-use the current +# console for output or return output as a string +function Exec-Command([string]$command, [string]$commandArgs, [switch]$useConsole = $false, [switch]$echoCommand = $true) { + if ($args -ne "") { + throw "Extra arguments passed to Exec-Command: $args" + } + Exec-CommandCore -command $command -commandArgs $commandArgs -useConsole:$useConsole -echoCommand:$echoCommand } # Handy function for executing a powershell script in a clean environment with # arguments. Prefer this over & sourcing a script as it will both use a clean # environment and do proper error checking -function Exec-Script([string]$script, [string]$scriptArgs = "") { - Exec-Command "pwsh" "-noprofile -executionPolicy RemoteSigned -file `"$script`" $scriptArgs" +# +# The -useConsole argument controls if the process should re-use the current +# console for output or return output as a string +function Exec-Script([string]$script, [string]$scriptArgs = "", [switch]$useConsole = $true, [switch]$echoCommand = $true) { + if ($args -ne "") { + throw "Extra arguments passed to Exec-Script: $args" + } + Exec-CommandCore -command "pwsh" -commandArgs "-noprofile -executionPolicy RemoteSigned -file `"$script`" $scriptArgs" -useConsole:$useConsole -echoCommand:$echoCommand } +# Handy function for executing a dotnet command without having to track down the +# proper dotnet executable or ensure it's on the path. +function Exec-DotNet([string]$commandArgs = "", [switch]$useConsole = $true, [switch]$echoCommand = $true) { + if ($args -ne "") { + throw "Extra arguments passed to Exec-DotNet: $args" + } + $dotnet = Ensure-DotNetSdk + Exec-CommandCore -command $dotnet -commandArgs $commandArgs -useConsole:$useConsole -echoCommand:$echoCommand +} + + # Ensure the proper .NET Core SDK is available. Returns the location to the dotnet.exe. function Ensure-DotnetSdk() { $dotnetInstallDir = (InitializeDotNetCli -install:$true) @@ -262,91 +276,6 @@ function Get-PackageDir([string]$name, [string]$version = "") { return $p } -# Create a bootstrap build of the compiler. Returns the directory where the bootstrap build -# is located. -# -# Important to not set $script:bootstrapDir here yet as we're actually in the process of -# building the bootstrap. -function Make-BootstrapBuild([string]$bootstrapToolset = "") { - - function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string]$logFileName = "", [string]$configuration = $script:configuration) { - # Because we override the C#/VB toolset to build against our LKG package, it is important - # that we do not reuse MSBuild nodes from other jobs/builds on the machine. Otherwise, - # we'll run into issues such as https://github.com/dotnet/roslyn/issues/6211. - # MSBuildAdditionalCommandLineArgs= - $args = "/p:TreatWarningsAsErrors=true /nologo /nodeReuse:false /p:Configuration=$configuration /v:m "; - - if ($warnAsError) { - $args += " /warnaserror" - } - - if ($runAnalyzers) { - $args += " /p:RunAnalyzersDuringBuild=true" - } - - if ($binaryLog) { - if ($logFileName -eq "") { - $logFileName = [IO.Path]::GetFileNameWithoutExtension($projectFilePath) - } - $logFileName = [IO.Path]::ChangeExtension($logFileName, ".binlog") - $logFilePath = Join-Path $LogDir $logFileName - $args += " /bl:$logFilePath" - } - - if ($officialBuildId) { - $args += " /p:OfficialBuildId=" + $officialBuildId - } - - if ($ci) { - $args += " /p:ContinuousIntegrationBuild=true" - } - - if ($bootstrapDir -ne "") { - $args += " /p:BootstrapBuildPath=$bootstrapDir" - } - - $args += " $buildArgs" - $args += " $projectFilePath" - $args += " $properties" - - $buildTool = InitializeBuildTool - Exec-Console $buildTool.Path "$($buildTool.Command) $args" - } - - Write-Host "Building bootstrap compiler" - - $dir = Join-Path $ArtifactsDir "Bootstrap" - Remove-Item -re $dir -ErrorAction SilentlyContinue - Create-Directory $dir - - if ($bootstrapToolset -eq "" -or $bootstrapToolset -eq "AnyCPU") { - $projectPath = "src\NuGet\Microsoft.Net.Compilers.Toolset\AnyCpu\Microsoft.Net.Compilers.Toolset.Package.csproj" - $packageName = "Microsoft.Net.Compilers.Toolset" - } - elseif ($bootstrapToolset -eq "Framework") { - $projectPath = "src\NuGet\Microsoft.Net.Compilers.Toolset\Framework\Microsoft.Net.Compilers.Toolset.Framework.Package.csproj" - $packageName = "Microsoft.Net.Compilers.Toolset.Framework" - } - else { - throw "Unsupported bootstrap toolset $bootstrapToolset" - } - - Run-MSBuild $projectPath "/restore /t:Pack /p:RoslynEnforceCodeStyle=false /p:RunAnalyzersDuringBuild=false /p:DotNetUseShippingVersions=true /p:InitialDefineConstants=BOOTSTRAP /p:PackageOutputPath=`"$dir`" /p:EnableNgenOptimization=false /p:PublishWindowsPdb=false" -logFileName "Bootstrap" -configuration $bootstrapConfiguration - $packageFile = Get-ChildItem -Path $dir -Filter "$packageName.*.nupkg" - Unzip (Join-Path $dir $packageFile.Name) $dir - - Write-Host "Cleaning Bootstrap compiler artifacts" - Run-MSBuild $projectPath "/t:Clean" -logFileName "BootstrapClean" - - # Work around NuGet bug that doesn't correctly re-generate our project.assets.json files. - # Deleting everything forces a regen - # https://github.com/NuGet/Home/issues/12437 - Remove-Item -Recurse -Force (Join-Path $ArtifactsDir "bin") - Remove-Item -Recurse -Force (Join-Path $ArtifactsDir "obj") - - return $dir -} - function Subst-TempDir() { if ($ci) { Exec-Command "subst" "T: $TempDir" diff --git a/eng/build.ps1 b/eng/build.ps1 index 7bfdf49d1b4ed..43fbdfba4db4c 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -32,8 +32,7 @@ param ( # Options [switch]$bootstrap, - [string]$bootstrapConfiguration = "Release", - [string]$bootstrapToolset = "", + [string]$bootstrapDir = "", [switch][Alias('bl')]$binaryLog, [string]$binaryLogName = "", [switch]$ci, @@ -105,7 +104,7 @@ function Print-Usage() { Write-Host "Advanced settings:" Write-Host " -ci Set when running on CI server" Write-Host " -bootstrap Build using a bootstrap compilers" - Write-Host " -bootstrapConfiguration Build configuration for bootstrap compiler: 'Debug' or 'Release'" + Write-Host " -bootstrapDir Build using bootstrap compiler at specified location" Write-Host " -msbuildEngine Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)." Write-Host " -collectDumps Collect dumps from test runs" Write-Host " -runAnalyzers Run analyzers during build operations (short: -a)" @@ -180,6 +179,10 @@ function Process-Arguments() { $script:binaryLogName = "Build.binlog" } + if ($bootstrapDir -ne "") { + $script:bootstrap = $true + } + $anyUnit = $testDesktop -or $testCoreClr if ($anyUnit -and $testVsi) { Write-Host "Cannot combine unit and VSI testing" @@ -463,7 +466,7 @@ function TestUsingRunTests() { try { Write-Host "$runTests $args" - Exec-Console $dotnetExe "$runTests $args" + Exec-Command $dotnetExe "$runTests $args" } finally { Get-Process "xunit*" -ErrorAction SilentlyContinue | Stop-Process if ($ci) { @@ -588,7 +591,7 @@ function Deploy-VsixViaTool() { $vsixFile = Join-Path $VSSetupDir $vsixFileName $fullArg = "$baseArgs $vsixFile" Write-Host "`tInstalling $vsixFileName" - Exec-Console $vsixExe $fullArg + Exec-Command $vsixExe $fullArg } # Set up registry @@ -746,18 +749,10 @@ try { &(Ensure-DotNetSdk) tool restore } - try - { - if ($bootstrap) { - $bootstrapDir = Make-BootstrapBuild $bootstrapToolset - } - } - catch - { - if ($ci) { - Write-LogIssue -Type "error" -Message "(NETCORE_ENGINEERING_TELEMETRY=Build) Build failed" - } - throw $_ + if ($bootstrap -and $bootstrapDir -eq "") { + Write-Host "Building bootstrap Compiler" + Exec-Script (Join-Path $PSScriptRoot "make-bootstrap.ps1") "-name build -force -ci:$ci" + $bootstrapDir = Join-Path $ArtifactsDir "bootstrap" "build" } if ($restore -or $build -or $rebuild -or $pack -or $sign -or $publish) { diff --git a/eng/config/BannedSymbols.txt b/eng/config/BannedSymbols.txt index 54e13f8c172af..42fd708fa29ec 100644 --- a/eng/config/BannedSymbols.txt +++ b/eng/config/BannedSymbols.txt @@ -69,4 +69,5 @@ M:Microsoft.CodeAnalysis.CodeActions.CodeAction.GetOperationsAsync(System.Thread M:Microsoft.CodeAnalysis.CodeActions.CodeAction.GetPreviewOperationsAsync(System.Threading.CancellationToken); Use overload that takes a solution M:Microsoft.CodeAnalysis.CodeActions.CodeAction.ComputeOperationsAsync(System.Threading.CancellationToken); Use overload that takes progress M:Microsoft.CodeAnalysis.CodeActions.CodeAction.GetChangedSolutionAsync(CSystem.Threading.CancellationToken); Use overload that takes progress -M:Microsoft.CodeAnalysis.CodeActions.CodeAction.GetChangedDocumentAsync(CancellationToken); Use overload that takes progress \ No newline at end of file +M:Microsoft.CodeAnalysis.CodeActions.CodeAction.GetChangedDocumentAsync(CancellationToken); Use overload that takes progress +M:System.Diagnostics.Tracing.EventSource.WriteEvent(System.Int32,System.Object[]); Use WriteEventCore instead \ No newline at end of file diff --git a/eng/config/PublishData.json b/eng/config/PublishData.json index 02eaa254b8fd6..a293dc5ce31df 100644 --- a/eng/config/PublishData.json +++ b/eng/config/PublishData.json @@ -51,6 +51,8 @@ "Microsoft.CodeAnalysis.LanguageServer.alpine-x64": "vs-impl", "Microsoft.CodeAnalysis.LanguageServer.linux-arm64": "vs-impl", "Microsoft.CodeAnalysis.LanguageServer.linux-x64": "vs-impl", + "Microsoft.CodeAnalysis.LanguageServer.linux-musl-x64": "vs-impl", + "Microsoft.CodeAnalysis.LanguageServer.linux-musl-arm64": "vs-impl", "Microsoft.CodeAnalysis.LanguageServer.neutral": "vs-impl", "Microsoft.CodeAnalysis.LanguageServer.osx-arm64": "vs-impl", "Microsoft.CodeAnalysis.LanguageServer.osx-x64": "vs-impl", @@ -193,6 +195,15 @@ "vsMajorVersion": 17, "insertionTitlePrefix": "[d17.9]" }, + "release/dev17.10": { + "nugetKind": [ + "Shipping", + "NonShipping" + ], + "vsBranch": "rel/d17.10", + "vsMajorVersion": 17, + "insertionTitlePrefix": "[d17.10]" + }, "main": { "nugetKind": [ "Shipping", @@ -201,9 +212,9 @@ "vsBranch": "main", "vsMajorVersion": 17, "insertionCreateDraftPR": false, - "insertionTitlePrefix": "[d17.10]" + "insertionTitlePrefix": "[d17.10 P2]" }, - "dev/jorobich/fix-pr-val": { + "features/vscode_net8": { "nugetKind": [ "Shipping", "NonShipping" diff --git a/eng/generate-compiler-code.cmd b/eng/generate-compiler-code.cmd index 808137ef77cb7..98108945d1e07 100644 --- a/eng/generate-compiler-code.cmd +++ b/eng/generate-compiler-code.cmd @@ -1,3 +1,3 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\generate-compiler-code.ps1" %* +pwsh -noprofile -executionPolicy RemoteSigned -file "%~dp0\generate-compiler-code.ps1" %* diff --git a/eng/generate-compiler-code.ps1 b/eng/generate-compiler-code.ps1 index 7dc68f68088ed..8d8bb403d96eb 100644 --- a/eng/generate-compiler-code.ps1 +++ b/eng/generate-compiler-code.ps1 @@ -11,7 +11,7 @@ $ErrorActionPreference="Stop" function Run-Tool($projectFilePath, $toolArgs, $targetFramework) { $toolName = Split-Path -leaf $projectFilePath Write-Host "Running $toolName $toolArgs" - Exec-Console $dotnet "run --project $projectFilePath --framework $targetFramework $toolArgs" + Exec-DotNet "run --project $projectFilePath --framework $targetFramework $toolArgs" } function Run-LanguageCore($language, $languageSuffix, $languageDir, $syntaxProject, $errorFactsProject, $generatedDir, $generatedTestDir) { diff --git a/eng/make-bootstrap.cmd b/eng/make-bootstrap.cmd new file mode 100644 index 0000000000000..d081540d85808 --- /dev/null +++ b/eng/make-bootstrap.cmd @@ -0,0 +1,2 @@ +@echo off +pwsh -noprofile -file "%~dp0\make-bootstrap.ps1" %* \ No newline at end of file diff --git a/eng/make-bootstrap.ps1 b/eng/make-bootstrap.ps1 new file mode 100644 index 0000000000000..b9452046dc41a --- /dev/null +++ b/eng/make-bootstrap.ps1 @@ -0,0 +1,80 @@ +# Make a bootstrap compiler and install it into artifacts/bootstrap folder + +[CmdletBinding(PositionalBinding=$false)] +param ( + [string]$name = "local", + [string]$toolset = "Default", + [string]$configuration = "Release", + [switch]$force = $false, + [switch]$ci = $false +) + +Set-StrictMode -version 2.0 +$ErrorActionPreference="Stop" + +try { + + . (Join-Path $PSScriptRoot "build-utils.ps1") + + $bootstrapDir = Join-Path $ArtifactsDir "bootstrap" $name + Write-Host "Building bootstrap compiler into $bootstrapDir" + + if (Test-Path $bootstrapDir) { + if ($force) { + Write-Host "Removing existing bootstrap compiler" + Remove-Item -Recurse -Force $bootstrapDir + } + else { + Write-Host "Bootstrap compiler already exists. Use -force to rebuild" + exit 1 + } + } + + if ($toolset -ieq "Default") { + $projectPath = "src\NuGet\Microsoft.Net.Compilers.Toolset\AnyCpu\Microsoft.Net.Compilers.Toolset.Package.csproj" + $packageName = "Microsoft.Net.Compilers.Toolset" + } + elseif ($toolset -ieq "Framework") { + $projectPath = "src\NuGet\Microsoft.Net.Compilers.Toolset\Framework\Microsoft.Net.Compilers.Toolset.Framework.Package.csproj" + $packageName = "Microsoft.Net.Compilers.Toolset.Framework" + } + else { + throw "Unsupported bootstrap toolset $toolset" + } + + $binaryLogFilePath = Join-Path $LogDir "bootstrap-$($name).binlog" + + # Because we override the C#/VB toolset to build against our LKG package, it is important + # that we do not reuse MSBuild nodes from other jobs/builds on the machine. Otherwise, + # we'll run into issues such as https://github.com/dotnet/roslyn/issues/6211. + # MSBuildAdditionalCommandLineArgs= + $args = "/p:TreatWarningsAsErrors=true /warnaserror /nologo /nodeReuse:false /p:Configuration=$configuration /v:m"; + $args += " /p:RunAnalyzersDuringBuild=false /bl:$binaryLogFilePath" + $args += " /t:Pack /p:RoslynEnforceCodeStyle=false /p:DotNetUseShippingVersions=true /p:InitialDefineConstants=BOOTSTRAP" + $args += " /p:PackageOutputPath=$bootstrapDir /p:NgenOptimization=false /p:PublishWindowsPdb=false" + + if ($ci) { + $args += " /p:ContinuousIntegrationBuild=true" + } + + Exec-DotNet "build $args $projectPath" + + $packageFilePath = Get-ChildItem -Path $bootstrapDir -Filter "$packageName.*.nupkg" + Write-Host "Found package $packageFilePath" + Unzip $packageFilePath.FullName $bootstrapDir + + Write-Host "Cleaning up artifacts" + Exec-DotNet "build --no-restore /t:Clean $projectPath" + Exec-DotNet "build-server shutdown" + + exit 0 +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 +} +finally { + Pop-Location +} \ No newline at end of file diff --git a/eng/pipelines/build-bootstrap.yml b/eng/pipelines/build-bootstrap.yml index a184e03c6f484..bb3678676d99c 100644 --- a/eng/pipelines/build-bootstrap.yml +++ b/eng/pipelines/build-bootstrap.yml @@ -1,33 +1,40 @@ # Build bootstrap parameters: -- name: bootstrapToolset - type: string - default: '' -- name: bootstrapName +- name: toolset type: string default: '' steps: - template: checkout-windows-task.yml - - script: eng/test-build-correctness.cmd -configuration Release -enableDumps -bootstrapToolset ${{parameters.bootstrapToolset}} + - script: eng\make-bootstrap.cmd -ci -toolset ${{parameters.toolset}} -name "ci-bootstrap" + displayName: Build Bootstrap Compiler + + - script: eng/test-build-correctness.cmd -configuration Release -enableDumps -bootstrapDir $(Build.SourcesDirectory)/artifacts/bootstrap/ci-bootstrap displayName: Build - Validate correctness - template: publish-logs.yml parameters: - jobName: Correctness_Bootstrap_Build - ${{parameters.bootstrapName}} + jobName: Correctness_Bootstrap_Build - ${{parameters.toolset}} configuration: Release + - task: PublishBuildArtifacts@1 + displayName: Publish Bootstrap Compiler + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\bootstrap\ci-bootstrap' + ArtifactName: 'Bootstrap Compiler - ${{parameters.toolset}}' + publishLocation: Container + - task: PublishBuildArtifacts@1 displayName: Publish Artifact Packages inputs: PathtoPublish: '$(Build.SourcesDirectory)\artifacts\packages\Release\PreRelease' - ArtifactName: 'Bootstrap Packages - ${{parameters.bootstrapName}}' + ArtifactName: 'Bootstrap Packages - ${{parameters.toolset}}' publishLocation: Container - task: PublishBuildArtifacts@1 displayName: Publish VSIX Packages inputs: PathtoPublish: '$(Build.SourcesDirectory)\artifacts\VSSetup\Release\Installer' - ArtifactName: 'Bootstrap VSIX - ${{parameters.bootstrapName}}' + ArtifactName: 'Bootstrap VSIX - ${{parameters.toolset}}' publishLocation: Container diff --git a/eng/prepare-tests.ps1 b/eng/prepare-tests.ps1 index 6c5fee384d31a..9f6193392aeef 100644 --- a/eng/prepare-tests.ps1 +++ b/eng/prepare-tests.ps1 @@ -8,10 +8,10 @@ try { . (Join-Path $PSScriptRoot "build-utils.ps1") Push-Location $RepoRoot - $dotnet = Ensure-DotnetSdk # permissions issues make this a pain to do in PrepareTests itself. Remove-Item -Recurse -Force "$RepoRoot\artifacts\testPayload" -ErrorAction SilentlyContinue - Exec-Console $dotnet "$RepoRoot\artifacts\bin\PrepareTests\$configuration\net8.0\PrepareTests.dll --source $RepoRoot --destination $RepoRoot\artifacts\testPayload --dotnetPath `"$dotnet`"" + $dotnet = Ensure-DotNetSdk + Exec-Command $dotnet "exec $RepoRoot\artifacts\bin\PrepareTests\$configuration\net8.0\PrepareTests.dll --source $RepoRoot --destination $RepoRoot\artifacts\testPayload --dotnetPath `"$dotnet`"" exit 0 } catch { diff --git a/eng/publish-assets.ps1 b/eng/publish-assets.ps1 index cc8b36f874e67..a1a4139a8dcad 100644 --- a/eng/publish-assets.ps1 +++ b/eng/publish-assets.ps1 @@ -102,7 +102,7 @@ function Publish-Nuget($publishData, [string]$packageDir) { if (-not $test) { Write-Host "Publishing $nupkg" - Exec-Console $dotnet "nuget push $nupkg --source $uploadUrl --api-key $apiKey" + Exec-DotNet "nuget push $nupkg --source $uploadUrl --api-key $apiKey" } } } diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets index d6a14c420ced6..0fddfdc7a1a36 100644 --- a/eng/targets/Imports.targets +++ b/eng/targets/Imports.targets @@ -3,6 +3,7 @@ + $(MSBuildWarningsAsMessages);NETSDK1206 - + + + + + + + + + + diff --git a/eng/targets/WpfTempProjectWorkarounds.targets b/eng/targets/WpfTempProjectWorkarounds.targets new file mode 100644 index 0000000000000..4bd62151bc2f6 --- /dev/null +++ b/eng/targets/WpfTempProjectWorkarounds.targets @@ -0,0 +1,7 @@ + + + + diff --git a/eng/test-build-correctness.cmd b/eng/test-build-correctness.cmd index 568cacecd3ec4..1a26bbd2d41ed 100644 --- a/eng/test-build-correctness.cmd +++ b/eng/test-build-correctness.cmd @@ -1,2 +1,2 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\test-build-correctness.ps1" %* +pwsh -noprofile -file "%~dp0\test-build-correctness.ps1" %* diff --git a/eng/test-build-correctness.ps1 b/eng/test-build-correctness.ps1 index 5114c2669ec2f..0e13c46e8f4f1 100644 --- a/eng/test-build-correctness.ps1 +++ b/eng/test-build-correctness.ps1 @@ -13,7 +13,8 @@ param( [string]$configuration = "Debug", [switch]$enableDumps = $false, - [string]$bootstrapToolset = "AnyCPU", + [string]$bootstrapDir = "", + [switch]$ci = $false, [switch]$help) Set-StrictMode -version 2.0 @@ -41,29 +42,35 @@ try { New-ItemProperty -Path $key -Name 'DumpFolder' -PropertyType 'String' -Value $LogDir -Force } + if ($bootstrapDir -eq "") { + Write-Host "Building bootstrap compiler" + Exec-Script (Join-Path $PSScriptRoot "make-bootstrap.ps1") "-name correctness -ci:$ci" + $bootstrapDir = Join-Path $ArtifactsDir "bootstrap" "correctness" + } + Write-Host "Building Roslyn" - Exec-Script (Join-Path $PSScriptRoot "build.ps1") "-restore -build -bootstrap -bootstrapConfiguration:Debug -bootstrapToolset:$bootstrapToolset -ci:$true -prepareMachine:$true -runAnalyzers:$true -configuration:$configuration -pack -binaryLog -useGlobalNuGetCache:$false -warnAsError:$true -properties `"/p:RoslynEnforceCodeStyle=true`"" + Exec-Script (Join-Path $PSScriptRoot "build.ps1") "-restore -build -bootstrapDir:$bootstrapDir -ci:$true -prepareMachine:$true -runAnalyzers:$true -configuration:$configuration -pack -binaryLog -useGlobalNuGetCache:$false -warnAsError:$true -properties `"/p:RoslynEnforceCodeStyle=true`"" Subst-TempDir # Verify the state of our various build artifacts Write-Host "Running BuildBoss" $buildBossPath = GetProjectOutputBinary "BuildBoss.exe" - Write-Host "$buildBossPath -r `"$RepoRoot/`" -c $configuration -p Roslyn.sln" - Exec-Console $buildBossPath "-r `"$RepoRoot/`" -c $configuration" -p Roslyn.sln + Exec-Command $buildBossPath "-r `"$RepoRoot/`" -c $configuration -p Roslyn.sln" Write-Host "" # Verify the state of our generated syntax files Write-Host "Checking generated compiler files" Exec-Script (Join-Path $PSScriptRoot "generate-compiler-code.ps1") "-test -configuration:$configuration" - Exec-Console dotnet "tool run dotnet-format whitespace . --folder --include-generated --include src/Compilers/CSharp/Portable/Generated/ src/Compilers/VisualBasic/Portable/Generated/ src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/Generated/ --verify-no-changes" + Exec-Command dotnet "tool run dotnet-format whitespace . --folder --include-generated --include src/Compilers/CSharp/Portable/Generated/ src/Compilers/VisualBasic/Portable/Generated/ src/ExpressionEvaluator/VisualBasic/Source/ResultProvider/Generated/ --verify-no-changes" Write-Host "" exit 0 } -catch [exception] { +catch { Write-Host $_ Write-Host $_.Exception + Write-Host $_.ScriptStackTrace Write-Host "##vso[task.logissue type=error]How to investigate bootstrap failures: https://github.com/dotnet/roslyn/blob/main/docs/compilers/Bootstrap%20Builds.md#Investigating" exit 1 } diff --git a/eng/test-determinism.cmd b/eng/test-determinism.cmd index 972f85371e6b2..e090fc5a3edb6 100644 --- a/eng/test-determinism.cmd +++ b/eng/test-determinism.cmd @@ -1,2 +1,2 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\test-determinism.ps1" %* +pwsh -noprofile -file "%~dp0\test-determinism.ps1" %* diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index 037a3b7c0a0f3..9643e4b60729f 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -2,6 +2,8 @@ param([string]$configuration = "Debug", [string]$msbuildEngine = "vs", [string]$altRootDrive = "q:", + [string]$bootstrapDir = "", + [switch]$ci = $false, [switch]$help) Set-StrictMode -version 2.0 @@ -281,8 +283,11 @@ try { $nodeReuse = $false $properties = @() - $script:bootstrapConfiguration = "Release" - $bootstrapDir = Make-BootstrapBuild + if ($bootstrapDir -eq "") { + Write-Host "Building bootstrap compiler" + Exec-Script (Join-Path $PSScriptRoot "make-bootstrap.ps1") "-name determinism -ci:$ci" + $bootstrapDir = Join-Path $ArtifactsDir "bootstrap" "determinism" + } Run-Test exit 0 diff --git a/eng/test-rebuild.cmd b/eng/test-rebuild.cmd new file mode 100644 index 0000000000000..a1c7084cccd91 --- /dev/null +++ b/eng/test-rebuild.cmd @@ -0,0 +1,2 @@ +@echo off +pwsh -noprofile -file "%~dp0\test-rebuild.ps1" %* diff --git a/eng/test-rebuild.ps1 b/eng/test-rebuild.ps1 index 045fd84b3356d..8e45c47cd943d 100644 --- a/eng/test-rebuild.ps1 +++ b/eng/test-rebuild.ps1 @@ -8,7 +8,7 @@ param( [switch]$ci = $false, [switch]$prepareMachine = $false, [switch]$useGlobalNuGetCache = $true, - [switch]$noBuild = $false, + [switch]$bootstrap = $false, [switch]$help) Set-StrictMode -version 2.0 @@ -19,7 +19,7 @@ function Print-Usage() { Write-Host " -configuration Build configuration ('Debug' or 'Release')" Write-Host " -ci Set when running on CI server" Write-Host " -useGlobalNuGetCache Use global NuGet cache." - Write-Host " -noBuild If set, skips running a bootstrap build before running the rebuild" + Write-Host " -bootstrap Do a bootstrap build before running the build validatior" Write-Host " -help Print help and exit" } @@ -32,9 +32,9 @@ try { . (Join-Path $PSScriptRoot "build-utils.ps1") Push-Location $RepoRoot - if (-not $noBuild) { + if ($bootstrap) { Write-Host "Building Roslyn" - Exec-Block { & (Join-Path $PSScriptRoot "build.ps1") -restore -build -bootstrap -prepareMachine:$prepareMachine -ci:$ci -useGlobalNuGetCache:$useGlobalNuGetCache -configuration:$configuration -pack -binaryLog } + Exec-Script (Join-Path $PSScriptRoot "build.ps1") "-restore -build -bootstrap -prepareMachine:$prepareMachine -ci:$ci -useGlobalNuGetCache:$useGlobalNuGetCache -configuration:$configuration -pack -binaryLog" } Subst-TempDir @@ -68,14 +68,15 @@ try { " --sourcePath `"$RepoRoot/`"" + " --referencesPath `"$ArtifactsDir/bin`"" + " --referencesPath `"$dotnetInstallDir/packs`"") - Exec-Console "$ArtifactsDir/bin/BuildValidator/$configuration/net472/BuildValidator.exe" $rebuildArgs + Exec-Command "$ArtifactsDir/bin/BuildValidator/$configuration/net472/BuildValidator.exe" $rebuildArgs exit 0 } -catch [exception] { +catch { Write-Host $_ Write-Host $_.Exception - exit 1 + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 } finally { Unsubst-TempDir diff --git a/eng/validate-code-formatting.ps1 b/eng/validate-code-formatting.ps1 index 203f7c36a4069..89ef02ba22a86 100644 --- a/eng/validate-code-formatting.ps1 +++ b/eng/validate-code-formatting.ps1 @@ -9,8 +9,7 @@ try { . (Join-Path $PSScriptRoot "build-utils.ps1") Push-Location $RepoRoot - $dotnet = Ensure-DotnetSdk - Exec-Console $dotnet "tool run dotnet-format -v detailed whitespace $rootDirectory --folder --include-generated --include $includeDirectories --verify-no-changes" + Exec-DotNet "tool run dotnet-format -v detailed whitespace $rootDirectory --folder --include-generated --include $includeDirectories --verify-no-changes" exit 0 } diff --git a/eng/validate-rules-missing-documentation.cmd b/eng/validate-rules-missing-documentation.cmd index c67f4927e835f..f90d3a1a973e7 100644 --- a/eng/validate-rules-missing-documentation.cmd +++ b/eng/validate-rules-missing-documentation.cmd @@ -1,2 +1,2 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\validate-rules-missing-documentation.ps1" %* +pwsh -noprofile -executionPolicy RemoteSigned -file "%~dp0\validate-rules-missing-documentation.ps1" %* diff --git a/eng/validate-rules-missing-documentation.ps1 b/eng/validate-rules-missing-documentation.ps1 index 2dd46bc64feeb..99775839c7efe 100644 --- a/eng/validate-rules-missing-documentation.ps1 +++ b/eng/validate-rules-missing-documentation.ps1 @@ -12,9 +12,8 @@ try { . (Join-Path $PSScriptRoot "build-utils.ps1") Push-Location $RepoRoot - $dotnet = Ensure-DotnetSdk $projectFilePath = Join-Path $RepoRoot "src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj" - Exec-Console $dotnet "build $projectFilePath -t:GenerateRulesMissingDocumentation -p:RoslynEnforceCodeStyle=false -p:RunAnalyzersDuringBuild=false -p:ContinuousIntegrationBuild=$ci -c Release" + Exec-DotNet "build $projectFilePath -t:GenerateRulesMissingDocumentation -p:RoslynEnforceCodeStyle=false -p:RunAnalyzersDuringBuild=false -p:ContinuousIntegrationBuild=$ci -c Release" if ($LASTEXITCODE -ne 0) { Write-Host "Failed with exit code $LASTEXITCODE." diff --git a/global.json b/global.json index 85f9d7cb99c14..5db0afcd2453a 100644 --- a/global.json +++ b/global.json @@ -14,6 +14,6 @@ "msbuild-sdks": { "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24059.4", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24059.4", - "Microsoft.Build.Traversal" : "3.4.0" + "Microsoft.Build.Traversal": "3.4.0" } } diff --git a/scripts/vscode-build.ps1 b/scripts/vscode-build.ps1 index c48e78d6eee01..42f3c0475b9c1 100644 --- a/scripts/vscode-build.ps1 +++ b/scripts/vscode-build.ps1 @@ -16,8 +16,7 @@ if ($projectFileInfo) { $frameworkArg = if ($framework -ne "") { " -p:TargetFramework=$framework" } else { "" } $buildArgs = "$($buildTool.Command) -v:m -m -p:RunAnalyzersDuringBuild=false -p:GenerateFullPaths=true$frameworkArg $($projectFileInfo.FullName)" - Write-Host "$($buildTool.Path) $buildArgs" - Exec-Console $buildTool.Path $buildArgs + Exec-Command $buildTool.Path $buildArgs exit 0 } else { diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs index 8c6f401471361..a313c1d8a5d35 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs @@ -11,23 +11,26 @@ using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryCast +namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryCast; + +/// +/// Supports simplifying cast expressions like (T)x as well as try-cast expressions like x as T +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +internal sealed class CSharpRemoveUnnecessaryCastDiagnosticAnalyzer + : AbstractRemoveUnnecessaryCastDiagnosticAnalyzer { - /// - /// Supports simplifying cast expressions like (T)x as well as try-cast expressions like x as T - /// - [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal sealed class CSharpRemoveUnnecessaryCastDiagnosticAnalyzer - : AbstractRemoveUnnecessaryCastDiagnosticAnalyzer - { - protected override ImmutableArray SyntaxKindsOfInterest { get; } = - [SyntaxKind.CastExpression, SyntaxKind.AsExpression]; + protected override ImmutableArray SyntaxKindsOfInterest { get; } = + [SyntaxKind.CastExpression, SyntaxKind.AsExpression]; - protected override bool IsUnnecessaryCast(SemanticModel model, ExpressionSyntax cast, CancellationToken cancellationToken) - => CastSimplifier.IsUnnecessaryCast(cast, model, cancellationToken); + protected override bool IsUnnecessaryCast(SemanticModel model, ExpressionSyntax cast, CancellationToken cancellationToken) + => CastSimplifier.IsUnnecessaryCast(cast, model, cancellationToken); - protected override TextSpan GetFadeSpan(ExpressionSyntax node) - => node is CastExpressionSyntax cast ? TextSpan.FromBounds(cast.OpenParenToken.SpanStart, cast.CloseParenToken.Span.End) : - node is BinaryExpressionSyntax binary ? TextSpan.FromBounds(binary.OperatorToken.SpanStart, node.Span.End) : throw ExceptionUtilities.Unreachable(); - } + protected override TextSpan GetFadeSpan(ExpressionSyntax node) + => node switch + { + CastExpressionSyntax cast => TextSpan.FromBounds(cast.OpenParenToken.SpanStart, cast.CloseParenToken.Span.End), + BinaryExpressionSyntax binary => TextSpan.FromBounds(binary.OperatorToken.SpanStart, node.Span.End), + _ => throw ExceptionUtilities.Unreachable(), + }; } diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs index 221b3d10f41d9..0399a28368ea6 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs @@ -11,136 +11,140 @@ using Microsoft.CodeAnalysis.Utilities; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.CSharp.RemoveUnreachableCode +namespace Microsoft.CodeAnalysis.CSharp.RemoveUnreachableCode; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +internal class CSharpRemoveUnreachableCodeDiagnosticAnalyzer : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer { - [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpRemoveUnreachableCodeDiagnosticAnalyzer : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer + private const string CS0162 = nameof(CS0162); // Unreachable code detected + + public const string IsSubsequentSection = nameof(IsSubsequentSection); + private static readonly ImmutableDictionary s_subsequentSectionProperties = ImmutableDictionary.Empty.Add(IsSubsequentSection, ""); + + public CSharpRemoveUnreachableCodeDiagnosticAnalyzer() + : base(IDEDiagnosticIds.RemoveUnreachableCodeDiagnosticId, + EnforceOnBuildValues.RemoveUnreachableCode, + option: null, + fadingOption: FadingOptions.FadeOutUnreachableCode, + new LocalizableResourceString(nameof(CSharpAnalyzersResources.Unreachable_code_detected), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), + configurable: false) { - private const string CS0162 = nameof(CS0162); // Unreachable code detected - - public const string IsSubsequentSection = nameof(IsSubsequentSection); - private static readonly ImmutableDictionary s_subsequentSectionProperties = ImmutableDictionary.Empty.Add(IsSubsequentSection, ""); - - public CSharpRemoveUnreachableCodeDiagnosticAnalyzer() - : base(IDEDiagnosticIds.RemoveUnreachableCodeDiagnosticId, - EnforceOnBuildValues.RemoveUnreachableCode, - option: null, - fadingOption: FadingOptions.FadeOutUnreachableCode, - new LocalizableResourceString(nameof(CSharpAnalyzersResources.Unreachable_code_detected), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), - configurable: false) - { - } + } - public override DiagnosticAnalyzerCategory GetAnalyzerCategory() - => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() + => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; - protected override void InitializeWorker(AnalysisContext context) - => context.RegisterSemanticModelAction(AnalyzeSemanticModel); + protected override void InitializeWorker(AnalysisContext context) + => context.RegisterSemanticModelAction(AnalyzeSemanticModel); - private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) + private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) + { + if (ShouldSkipAnalysis(context, notification: null)) + return; + + var semanticModel = context.SemanticModel; + var cancellationToken = context.CancellationToken; + + // There is no good existing API to check if a statement is unreachable in an efficient + // manner. While there is SemanticModel.AnalyzeControlFlow, it can only operate on a + // statement at a time, and it will reanalyze and allocate on each call. + // + // To avoid this, we simply ask the semantic model for all the diagnostics for this + // block and we look for any reported "unreachable code detected" diagnostics. + // + // This is actually quite fast to do because the compiler does not actually need to + // recompile things to determine the diagnostics. It will have already stashed the + // binding diagnostics directly on the SourceMethodSymbol containing this block, and + // so it can retrieve the diagnostics at practically no cost. + var root = semanticModel.SyntaxTree.GetRoot(cancellationToken); + var diagnostics = semanticModel.GetDiagnostics(context.FilterSpan, cancellationToken); + foreach (var diagnostic in diagnostics) { - if (ShouldSkipAnalysis(context, notification: null)) - return; - - var semanticModel = context.SemanticModel; - var cancellationToken = context.CancellationToken; - - // There is no good existing API to check if a statement is unreachable in an efficient - // manner. While there is SemanticModel.AnalyzeControlFlow, it can only operate on a - // statement at a time, and it will reanalyze and allocate on each call. - // - // To avoid this, we simply ask the semantic model for all the diagnostics for this - // block and we look for any reported "unreachable code detected" diagnostics. - // - // This is actually quite fast to do because the compiler does not actually need to - // recompile things to determine the diagnostics. It will have already stashed the - // binding diagnostics directly on the SourceMethodSymbol containing this block, and - // so it can retrieve the diagnostics at practically no cost. - var root = semanticModel.SyntaxTree.GetRoot(cancellationToken); - var diagnostics = semanticModel.GetDiagnostics(context.FilterSpan, cancellationToken); - foreach (var diagnostic in diagnostics) - { - cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); - if (diagnostic.Id == CS0162) - { - ProcessUnreachableDiagnostic(context, root, diagnostic.Location.SourceSpan); - } + if (diagnostic.Id == CS0162) + { + ProcessUnreachableDiagnostic(context, root, diagnostic.Location.SourceSpan); } } + } - private void ProcessUnreachableDiagnostic( - SemanticModelAnalysisContext context, SyntaxNode root, TextSpan sourceSpan) + public static StatementSyntax? TryGetContainingStatement(SyntaxNode node) + { + var firstUnreachableStatement = node.FirstAncestorOrSelf(); + return firstUnreachableStatement != null && firstUnreachableStatement.SpanStart == node.SpanStart + ? firstUnreachableStatement + : null; + } + + private void ProcessUnreachableDiagnostic( + SemanticModelAnalysisContext context, SyntaxNode root, TextSpan sourceSpan) + { + var node = root.FindNode(sourceSpan); + + // Note: this approach works as the language only supports the concept of + // unreachable statements. If we ever get unreachable subexpressions, then + // we'll need to revise this code accordingly. + var firstUnreachableStatement = TryGetContainingStatement(node); + if (firstUnreachableStatement is null) + return; + + // At a high level, we can think about us wanting to fade out a "section" of unreachable + // statements. However, the compiler only reports the first statement in that "section". + // We want to figure out what other statements are in that section and fade them all out + // along with the first statement. This is made somewhat tricky due to the fact that + // subsequent sibling statements possibly being reachable due to explicit gotos+labels. + // + // On top of this, an unreachable section might not be contiguous. This is possible + // when there is unreachable code that contains a local function declaration in-situ. + // This is legal, and the local function declaration may be called from other reachable code. + // + // As such, it's not possible to just get first unreachable statement, and the last, and + // then report that whole region as unreachable. Instead, when we are told about an + // unreachable statement, we simply determine which other statements are also unreachable + // and bucket them into contiguous chunks. + // + // We then fade each of these contiguous chunks, while also having each diagnostic we + // report point back to the first unreachable statement so that we can easily determine + // what to remove if the user fixes the issue. (The fix itself has to go recompute this + // as the total set of statements to remove may be larger than the actual faded code + // that that diagnostic corresponds to). + + // Get the location of this first unreachable statement. It will be given to all + // the diagnostics we create off of this single compiler diagnostic so that we always + // know how to find it regardless of which of our diagnostics the user invokes the + // fix off of. + var firstStatementLocation = root.SyntaxTree.GetLocation(firstUnreachableStatement.FullSpan); + + // 'additionalLocations' is how we always pass along the locaiton of the first unreachable + // statement in this group. + var additionalLocations = ImmutableArray.Create(firstStatementLocation); + + context.ReportDiagnostic(DiagnosticHelper.CreateWithLocationTags( + Descriptor, + firstStatementLocation, + NotificationOption2.ForSeverity(Descriptor.DefaultSeverity), + additionalLocations: [], + additionalUnnecessaryLocations: additionalLocations)); + + var sections = RemoveUnreachableCodeHelpers.GetSubsequentUnreachableSections(firstUnreachableStatement); + foreach (var section in sections) { - var node = root.FindNode(sourceSpan); - - // Note: this approach works as the language only supports the concept of - // unreachable statements. If we ever get unreachable subexpressions, then - // we'll need to revise this code accordingly. - var firstUnreachableStatement = node.FirstAncestorOrSelf(); - if (firstUnreachableStatement == null || - firstUnreachableStatement.SpanStart != sourceSpan.Start) - { - return; - } + var span = TextSpan.FromBounds(section[0].FullSpan.Start, section.Last().FullSpan.End); + var location = root.SyntaxTree.GetLocation(span); - // At a high level, we can think about us wanting to fade out a "section" of unreachable - // statements. However, the compiler only reports the first statement in that "section". - // We want to figure out what other statements are in that section and fade them all out - // along with the first statement. This is made somewhat tricky due to the fact that - // subsequent sibling statements possibly being reachable due to explicit gotos+labels. - // - // On top of this, an unreachable section might not be contiguous. This is possible - // when there is unreachable code that contains a local function declaration in-situ. - // This is legal, and the local function declaration may be called from other reachable code. - // - // As such, it's not possible to just get first unreachable statement, and the last, and - // then report that whole region as unreachable. Instead, when we are told about an - // unreachable statement, we simply determine which other statements are also unreachable - // and bucket them into contiguous chunks. - // - // We then fade each of these contiguous chunks, while also having each diagnostic we - // report point back to the first unreachable statement so that we can easily determine - // what to remove if the user fixes the issue. (The fix itself has to go recompute this - // as the total set of statements to remove may be larger than the actual faded code - // that that diagnostic corresponds to). - - // Get the location of this first unreachable statement. It will be given to all - // the diagnostics we create off of this single compiler diagnostic so that we always - // know how to find it regardless of which of our diagnostics the user invokes the - // fix off of. - var firstStatementLocation = root.SyntaxTree.GetLocation(firstUnreachableStatement.FullSpan); - - // 'additionalLocations' is how we always pass along the locaiton of the first unreachable - // statement in this group. - var additionalLocations = ImmutableArray.Create(firstStatementLocation); + // Mark subsequent sections as being 'cascaded'. We don't need to actually process them + // when doing a fix-all as they'll be scooped up when we process the fix for the first + // section. + var additionalUnnecessaryLocations = ImmutableArray.Create(location); context.ReportDiagnostic(DiagnosticHelper.CreateWithLocationTags( Descriptor, - firstStatementLocation, + location, NotificationOption2.ForSeverity(Descriptor.DefaultSeverity), - additionalLocations: [], - additionalUnnecessaryLocations: additionalLocations)); - - var sections = RemoveUnreachableCodeHelpers.GetSubsequentUnreachableSections(firstUnreachableStatement); - foreach (var section in sections) - { - var span = TextSpan.FromBounds(section[0].FullSpan.Start, section.Last().FullSpan.End); - var location = root.SyntaxTree.GetLocation(span); - - // Mark subsequent sections as being 'cascaded'. We don't need to actually process them - // when doing a fix-all as they'll be scooped up when we process the fix for the first - // section. - var additionalUnnecessaryLocations = ImmutableArray.Create(location); - - context.ReportDiagnostic(DiagnosticHelper.CreateWithLocationTags( - Descriptor, - location, - NotificationOption2.ForSeverity(Descriptor.DefaultSeverity), - additionalLocations, - additionalUnnecessaryLocations, - s_subsequentSectionProperties)); - } + additionalLocations, + additionalUnnecessaryLocations, + s_subsequentSectionProperties)); } } } diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer.cs index 21bba48128246..86ab0bebb8503 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Shared.CodeStyle; @@ -47,8 +48,8 @@ private void AnalyzeArrayCreationExpression(SyntaxNodeAnalysisContext context, I return; // Analyze the statements that follow to see if they can initialize this array. - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; - var matches = TryGetMatches(semanticModel, arrayCreationExpression, expressionType, allowInterfaceConversion, cancellationToken, out var changesSemantics); + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + var matches = TryGetMatches(semanticModel, arrayCreationExpression, expressionType, allowSemanticsChange, cancellationToken, out var changesSemantics); if (matches.IsDefault) return; @@ -59,7 +60,7 @@ public static ImmutableArray> TryGetM SemanticModel semanticModel, ArrayCreationExpressionSyntax expression, INamedTypeSymbol? expressionType, - bool allowInterfaceConversion, + bool allowSemanticsChange, CancellationToken cancellationToken, out bool changesSemantics) { @@ -70,7 +71,7 @@ public static ImmutableArray> TryGetM expression, expressionType, isSingletonInstance: false, - allowInterfaceConversion, + allowSemanticsChange, static e => e.Type, static e => e.Initializer, cancellationToken, @@ -79,11 +80,34 @@ public static ImmutableArray> TryGetM return default; if (!UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression( - semanticModel, expression, expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics)) + semanticModel, expression, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics)) { return default; } + // If we have an initializer that itself is only full of collection expressions (like `{ ["a"], ["b"] }`), then + // we can only convert if the final type we're converting to has an element type that itself is a collection type. + if (expression.Initializer is { Expressions.Count: > 0 } && + expression.Initializer.Expressions.All(e => e is CollectionExpressionSyntax)) + { + var convertedType = semanticModel.GetTypeInfo(expression.WalkUpParentheses(), cancellationToken).ConvertedType; + if (convertedType is null) + return default; + + var ienumerableType = convertedType.OriginalDefinition.SpecialType is SpecialType.System_Collections_Generic_IEnumerable_T + ? (INamedTypeSymbol)convertedType + : convertedType.AllInterfaces.FirstOrDefault( + i => i.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T); + if (ienumerableType is null) + return default; + + if (!UseCollectionExpressionHelpers.IsConstructibleCollectionType( + semanticModel.Compilation, ienumerableType.TypeArguments.Single())) + { + return default; + } + } + return matches; } @@ -91,14 +115,14 @@ public static ImmutableArray> TryGetM SemanticModel semanticModel, ImplicitArrayCreationExpressionSyntax expression, INamedTypeSymbol? expressionType, - bool allowInterfaceConversion, + bool allowSemanticsChange, CancellationToken cancellationToken, out bool changesSemantics) { // if we have `new[] { ... }` we have no subsequent matches to add to the collection. All values come // from within the initializer. if (!UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression( - semanticModel, expression, expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics)) + semanticModel, expression, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics)) { return default; } @@ -133,10 +157,10 @@ private void AnalyzeArrayInitializerExpression(SyntaxNodeAnalysisContext context var replacementCollectionExpression = CollectionExpression( [.. initializer.Expressions.Select(ExpressionElement)]); - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; if (!UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression( semanticModel, arrayCreationExpression, replacementCollectionExpression, - expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, + expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) { return; @@ -146,8 +170,8 @@ private void AnalyzeArrayInitializerExpression(SyntaxNodeAnalysisContext context { var matches = initializer.Parent switch { - ArrayCreationExpressionSyntax arrayCreation => TryGetMatches(semanticModel, arrayCreation, expressionType, allowInterfaceConversion, cancellationToken, out _), - ImplicitArrayCreationExpressionSyntax arrayCreation => TryGetMatches(semanticModel, arrayCreation, expressionType, allowInterfaceConversion, cancellationToken, out _), + ArrayCreationExpressionSyntax arrayCreation => TryGetMatches(semanticModel, arrayCreation, expressionType, allowSemanticsChange, cancellationToken, out _), + ImplicitArrayCreationExpressionSyntax arrayCreation => TryGetMatches(semanticModel, arrayCreation, expressionType, allowSemanticsChange, cancellationToken, out _), _ => throw ExceptionUtilities.Unreachable(), }; diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderDiagnosticAnalyzer.cs index 1e44e454f26d7..e2901f3eb0a27 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderDiagnosticAnalyzer.cs @@ -44,8 +44,8 @@ private void AnalyzeInvocationExpression( if (option.Value is CollectionExpressionPreference.Never || ShouldSkipAnalysis(context, option.Notification)) return; - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; - if (AnalyzeInvocation(semanticModel, invocationExpression, expressionType, allowInterfaceConversion, cancellationToken) is not { } analysisResult) + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + if (AnalyzeInvocation(semanticModel, invocationExpression, expressionType, allowSemanticsChange, cancellationToken) is not { } analysisResult) return; var locations = ImmutableArray.Create(invocationExpression.GetLocation()); @@ -98,7 +98,7 @@ void FadeOutCode(SyntaxNodeAnalysisContext context, AnalysisResult analysisResul SemanticModel semanticModel, InvocationExpressionSyntax invocationExpression, INamedTypeSymbol? expressionType, - bool allowInterfaceConversion, + bool allowSemanticsChange, CancellationToken cancellationToken) { // Looking for `XXX.CreateBuilder(...)` @@ -193,7 +193,7 @@ void FadeOutCode(SyntaxNodeAnalysisContext context, AnalysisResult analysisResul // Make sure we can actually use a collection expression in place of the created collection. if (!UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression( - semanticModel, creationExpression, expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) + semanticModel, creationExpression, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) { return null; } diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForCreateDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForCreateDiagnosticAnalyzer.cs index cc8c145fb40e6..c2be19e736cfc 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForCreateDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForCreateDiagnosticAnalyzer.cs @@ -44,9 +44,9 @@ private void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context, INam return; // Make sure we can actually use a collection expression in place of the full invocation. - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; if (!CanReplaceWithCollectionExpression( - semanticModel, invocationExpression, expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) + semanticModel, invocationExpression, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) { return; } diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForEmptyDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForEmptyDiagnosticAnalyzer.cs index d1bef1fdcc6e9..86f9b0ff8b2c1 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForEmptyDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForEmptyDiagnosticAnalyzer.cs @@ -45,9 +45,9 @@ private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context, INamedTypeSy if (nodeToReplace is null) return; - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; if (!CanReplaceWithCollectionExpression( - semanticModel, nodeToReplace, expressionType, isSingletonInstance: true, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) + semanticModel, nodeToReplace, expressionType, isSingletonInstance: true, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) { return; } diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForFluentDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForFluentDiagnosticAnalyzer.cs index 875c2f7acbb86..5679abe17fe0a 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForFluentDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForFluentDiagnosticAnalyzer.cs @@ -101,8 +101,8 @@ private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context, INamedTypeSy } var sourceText = semanticModel.SyntaxTree.GetText(cancellationToken); - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; - var analysisResult = AnalyzeInvocation(sourceText, state, invocation, expressionType, allowInterfaceConversion, addMatches: true, cancellationToken); + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + var analysisResult = AnalyzeInvocation(sourceText, state, invocation, expressionType, allowSemanticsChange, addMatches: true, cancellationToken); if (analysisResult is null) return; @@ -125,7 +125,7 @@ private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context, INamedTypeSy FluentState state, InvocationExpressionSyntax invocation, INamedTypeSymbol? expressionType, - bool allowInterfaceConversion, + bool allowSemanticsChange, bool addMatches, CancellationToken cancellationToken) { @@ -136,7 +136,7 @@ private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context, INamedTypeSy return null; if (!CanReplaceWithCollectionExpression( - state.SemanticModel, invocation, expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) + state.SemanticModel, invocation, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out var changesSemantics)) { return null; } diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocDiagnosticAnalyzer.cs index edd22ba5cd603..d619178c2d0f0 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocDiagnosticAnalyzer.cs @@ -49,7 +49,7 @@ private void AnalyzeImplicitStackAllocExpression(SyntaxNodeAnalysisContext conte // Stack alloc can never be wrapped in an interface, so don't even try. if (!UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression( - semanticModel, expression, expressionType, isSingletonInstance: false, allowInterfaceConversion: false, skipVerificationForReplacedNode: true, cancellationToken, out _)) + semanticModel, expression, expressionType, isSingletonInstance: false, allowSemanticsChange: false, skipVerificationForReplacedNode: true, cancellationToken, out _)) { return; } @@ -87,8 +87,8 @@ private void AnalyzeExplicitStackAllocExpression(SyntaxNodeAnalysisContext conte if (option.Value is CollectionExpressionPreference.Never || ShouldSkipAnalysis(context, option.Notification)) return; - var allowInterfaceConversion = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; - var matches = TryGetMatches(semanticModel, expression, expressionType, allowInterfaceConversion, cancellationToken); + var allowSemanticsChange = option.Value is CollectionExpressionPreference.WhenTypesLooselyMatch; + var matches = TryGetMatches(semanticModel, expression, expressionType, allowSemanticsChange, cancellationToken); if (matches.IsDefault) return; @@ -117,7 +117,7 @@ public static ImmutableArray> TryGetM SemanticModel semanticModel, StackAllocArrayCreationExpressionSyntax expression, INamedTypeSymbol? expressionType, - bool allowInterfaceConversion, + bool allowSemanticsChange, CancellationToken cancellationToken) { return UseCollectionExpressionHelpers.TryGetMatches( @@ -125,7 +125,7 @@ public static ImmutableArray> TryGetM expression, expressionType, isSingletonInstance: false, - allowInterfaceConversion, + allowSemanticsChange, static e => e.Type, static e => e.Initializer, cancellationToken, diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs index 010a3464ae7ce..9a08888a4ef41 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs @@ -40,7 +40,7 @@ public static bool CanReplaceWithCollectionExpression( ExpressionSyntax expression, INamedTypeSymbol? expressionType, bool isSingletonInstance, - bool allowInterfaceConversion, + bool allowSemanticsChange, bool skipVerificationForReplacedNode, CancellationToken cancellationToken, out bool changesSemantics) @@ -50,7 +50,7 @@ public static bool CanReplaceWithCollectionExpression( // something untyped. This will also tell us if we have any ambiguities (because there are multiple destination // types that could accept the collection expression). return CanReplaceWithCollectionExpression( - semanticModel, expression, s_emptyCollectionExpression, expressionType, isSingletonInstance, allowInterfaceConversion, skipVerificationForReplacedNode, cancellationToken, out changesSemantics); + semanticModel, expression, s_emptyCollectionExpression, expressionType, isSingletonInstance, allowSemanticsChange, skipVerificationForReplacedNode, cancellationToken, out changesSemantics); } public static bool CanReplaceWithCollectionExpression( @@ -59,7 +59,7 @@ public static bool CanReplaceWithCollectionExpression( CollectionExpressionSyntax replacementExpression, INamedTypeSymbol? expressionType, bool isSingletonInstance, - bool allowInterfaceConversion, + bool allowSemanticsChange, bool skipVerificationForReplacedNode, CancellationToken cancellationToken, out bool changesSemantics) @@ -88,7 +88,7 @@ public static bool CanReplaceWithCollectionExpression( if (originalTypeInfo.ConvertedType is null or IErrorTypeSymbol) return false; - if (!IsConstructibleCollectionType(originalTypeInfo.ConvertedType.OriginalDefinition)) + if (!IsConstructibleCollectionType(compilation, originalTypeInfo.ConvertedType.OriginalDefinition)) return false; if (expression.IsInExpressionTree(semanticModel, expressionType, cancellationToken)) @@ -111,7 +111,7 @@ public static bool CanReplaceWithCollectionExpression( // expression will always succeed, and there's no need to actually validate semantics there. // Tracked by https://github.com/dotnet/roslyn/issues/68826 if (parent is CastExpressionSyntax) - return IsConstructibleCollectionType(semanticModel.GetTypeInfo(parent, cancellationToken).Type); + return IsConstructibleCollectionType(compilation, semanticModel.GetTypeInfo(parent, cancellationToken).Type); // Looks good as something to replace. Now check the semantics of making the replacement to see if there would // any issues. @@ -146,70 +146,6 @@ public static bool CanReplaceWithCollectionExpression( return true; - bool IsConstructibleCollectionType(ITypeSymbol? type) - { - // Arrays are always a valid collection expression type. - if (type is IArrayTypeSymbol) - return true; - - // Has to be a real named type at this point. - if (type is INamedTypeSymbol namedType) - { - // Span and ReadOnlySpan are always valid collection expression types. - if (namedType.OriginalDefinition.Equals(compilation.SpanOfTType()) || - namedType.OriginalDefinition.Equals(compilation.ReadOnlySpanOfTType())) - { - return true; - } - - // If it has a [CollectionBuilder] attribute on it, it is a valid collection expression type. - if (namedType.GetAttributes().Any(a => a.AttributeClass.IsCollectionBuilderAttribute())) - return true; - - if (IsWellKnownInterface(namedType)) - return true; - - // At this point, all that is left are collection-initializer types. These need to derive from - // System.Collections.IEnumerable, and have an invokable no-arg constructor. - - // Abstract type don't have invokable constructors at all. - if (namedType.IsAbstract) - return false; - - if (namedType.AllInterfaces.Contains(compilation.IEnumerableType()!)) - { - // If they have an accessible `public C(int capacity)` constructor, the lang prefers calling that. - var constructors = namedType.Constructors; - var capacityConstructor = GetAccessibleInstanceConstructor(constructors, c => c.Parameters is [{ Name: "capacity", Type.SpecialType: SpecialType.System_Int32 }]); - if (capacityConstructor != null) - return true; - - var noArgConstructor = - GetAccessibleInstanceConstructor(constructors, c => c.Parameters.IsEmpty) ?? - GetAccessibleInstanceConstructor(constructors, c => c.Parameters.All(p => p.IsOptional || p.IsParams)); - if (noArgConstructor != null) - { - // If we have a struct, and the constructor we find is implicitly declared, don't consider this - // a constructible type. It's likely the user would just get the `default` instance of the - // collection (like with ImmutableArray) which would then not actually work. If the struct - // does have an explicit constructor though, that's a good sign it can actually be constructed - // safely with the no-arg `new S()` call. - if (!(namedType.TypeKind == TypeKind.Struct && noArgConstructor.IsImplicitlyDeclared)) - return true; - } - } - } - - // Anything else is not constructible. - return false; - } - - IMethodSymbol? GetAccessibleInstanceConstructor(ImmutableArray constructors, Func predicate) - { - var constructor = constructors.FirstOrDefault(c => !c.IsStatic && predicate(c)); - return constructor is not null && constructor.IsAccessibleWithin(compilation.Assembly) ? constructor : null; - } - bool IsSafeConversionWhenTypesDoNotMatch(out bool changesSemantics) { changesSemantics = false; @@ -254,39 +190,127 @@ bool IsSafeConversionWhenTypesDoNotMatch(out bool changesSemantics) if (s_tupleNamesCanDifferComparer.Equals(type, convertedType)) return true; - if (allowInterfaceConversion && - IsWellKnownInterface(convertedType) && - type.AllInterfaces.Contains(convertedType)) - { - // In the case of a singleton (like `Array.Empty()`) we don't want to convert to `IList` as that - // will replace the code with code that now always allocates. - if (isSingletonInstance && IsWellKnownReadWriteInterface(convertedType)) - return false; + // Before this point are all the changes that we can detect that are always safe to make. + if (!allowSemanticsChange) + return false; + + // After this point are all the changes that we can detect that may change runtime semantics (for example, + // converting an array into a compiler-generated IEnumerable), but which can be ok since the user has opted + // into allowing that. + changesSemantics = true; - changesSemantics = true; + // In the case of a singleton (like `Array.Empty()`) we don't want to convert to `IList` as that + // will replace the code with code that now always allocates. + if (isSingletonInstance && IsWellKnownCollectionReadWriteInterface(convertedType)) + return false; + + // Ok to convert in cases like: + // + // `IEnumerable obj = Array.Empty();` or + // `IEnumerable obj = new[] { "" };` + if (IsWellKnownCollectionInterface(convertedType) && type.AllInterfaces.Contains(convertedType)) return true; + + // Implicit reference array conversion is acceptable if the user is ok with semantics changing. For example: + // + // `object[] obj = new[] { "a" }` or + // `IEnumerable obj = new[] { "a" }` or + // + // Before the change this would be a string-array. With a collection expression this will become an object[]. + if (type is IArrayTypeSymbol) + { + var conversion = compilation.ClassifyConversion(type, convertedType); + if (conversion.IsIdentityOrImplicitReference()) + return true; } // Add more cases to support here. return false; } + } - bool IsWellKnownInterface(ITypeSymbol type) - => IsWellKnownReadOnlyInterface(type) || IsWellKnownReadWriteInterface(type); + public static bool IsWellKnownCollectionInterface(ITypeSymbol type) + => IsWellKnownCollectionReadOnlyInterface(type) || IsWellKnownCollectionReadWriteInterface(type); - bool IsWellKnownReadOnlyInterface(ITypeSymbol type) + public static bool IsWellKnownCollectionReadOnlyInterface(ITypeSymbol type) + { + return type.OriginalDefinition.SpecialType + is SpecialType.System_Collections_Generic_IEnumerable_T + or SpecialType.System_Collections_Generic_IReadOnlyCollection_T + or SpecialType.System_Collections_Generic_IReadOnlyList_T; + } + + public static bool IsWellKnownCollectionReadWriteInterface(ITypeSymbol type) + { + return type.OriginalDefinition.SpecialType + is SpecialType.System_Collections_Generic_ICollection_T + or SpecialType.System_Collections_Generic_IList_T; + } + + public static bool IsConstructibleCollectionType(Compilation compilation, ITypeSymbol? type) + { + if (type is null) + return false; + + // Arrays are always a valid collection expression type. + if (type is IArrayTypeSymbol) + return true; + + // Has to be a real named type at this point. + if (type is INamedTypeSymbol namedType) { - return type.OriginalDefinition.SpecialType - is SpecialType.System_Collections_Generic_IEnumerable_T - or SpecialType.System_Collections_Generic_IReadOnlyCollection_T - or SpecialType.System_Collections_Generic_IReadOnlyList_T; + // Span and ReadOnlySpan are always valid collection expression types. + if (namedType.OriginalDefinition.Equals(compilation.SpanOfTType()) || + namedType.OriginalDefinition.Equals(compilation.ReadOnlySpanOfTType())) + { + return true; + } + + // If it has a [CollectionBuilder] attribute on it, it is a valid collection expression type. + if (namedType.GetAttributes().Any(a => a.AttributeClass.IsCollectionBuilderAttribute())) + return true; + + if (IsWellKnownCollectionInterface(namedType)) + return true; + + // At this point, all that is left are collection-initializer types. These need to derive from + // System.Collections.IEnumerable, and have an invokable no-arg constructor. + + // Abstract type don't have invokable constructors at all. + if (namedType.IsAbstract) + return false; + + if (namedType.AllInterfaces.Contains(compilation.IEnumerableType()!)) + { + // If they have an accessible `public C(int capacity)` constructor, the lang prefers calling that. + var constructors = namedType.Constructors; + var capacityConstructor = GetAccessibleInstanceConstructor(constructors, c => c.Parameters is [{ Name: "capacity", Type.SpecialType: SpecialType.System_Int32 }]); + if (capacityConstructor != null) + return true; + + var noArgConstructor = + GetAccessibleInstanceConstructor(constructors, c => c.Parameters.IsEmpty) ?? + GetAccessibleInstanceConstructor(constructors, c => c.Parameters.All(p => p.IsOptional || p.IsParams)); + if (noArgConstructor != null) + { + // If we have a struct, and the constructor we find is implicitly declared, don't consider this + // a constructible type. It's likely the user would just get the `default` instance of the + // collection (like with ImmutableArray) which would then not actually work. If the struct + // does have an explicit constructor though, that's a good sign it can actually be constructed + // safely with the no-arg `new S()` call. + if (!(namedType.TypeKind == TypeKind.Struct && noArgConstructor.IsImplicitlyDeclared)) + return true; + } + } } - bool IsWellKnownReadWriteInterface(ITypeSymbol type) + // Anything else is not constructible. + return false; + + IMethodSymbol? GetAccessibleInstanceConstructor(ImmutableArray constructors, Func predicate) { - return type.OriginalDefinition.SpecialType - is SpecialType.System_Collections_Generic_ICollection_T - or SpecialType.System_Collections_Generic_IList_T; + var constructor = constructors.FirstOrDefault(c => !c.IsStatic && predicate(c)); + return constructor is not null && constructor.IsAccessibleWithin(compilation.Assembly) ? constructor : null; } } @@ -754,7 +778,7 @@ public static ImmutableArray> TryGetM TArrayCreationExpressionSyntax expression, INamedTypeSymbol? expressionType, bool isSingletonInstance, - bool allowInterfaceConversion, + bool allowSemanticsChange, Func getType, Func getInitializer, CancellationToken cancellationToken, @@ -861,7 +885,7 @@ public static ImmutableArray> TryGetM } if (!CanReplaceWithCollectionExpression( - semanticModel, expression, expressionType, isSingletonInstance, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics)) + semanticModel, expression, expressionType, isSingletonInstance, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics)) { return default; } diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs index cac1bd577fca8..9a7530ed1625c 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs @@ -40,6 +40,6 @@ protected override bool AreCollectionInitializersSupported(Compilation compilati protected override bool AreCollectionExpressionsSupported(Compilation compilation) => compilation.LanguageVersion().SupportsCollectionExpressions(); - protected override bool CanUseCollectionExpression(SemanticModel semanticModel, BaseObjectCreationExpressionSyntax objectCreationExpression, INamedTypeSymbol? expressionType, bool allowInterfaceConversion, CancellationToken cancellationToken, out bool changesSemantics) - => UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression(semanticModel, objectCreationExpression, expressionType, isSingletonInstance: false, allowInterfaceConversion, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics); + protected override bool CanUseCollectionExpression(SemanticModel semanticModel, BaseObjectCreationExpressionSyntax objectCreationExpression, INamedTypeSymbol? expressionType, bool allowSemanticsChange, CancellationToken cancellationToken, out bool changesSemantics) + => UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression(semanticModel, objectCreationExpression, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics); } diff --git a/src/Analyzers/CSharp/Analyzers/UseConditionalExpression/CSharpUseConditionalExpressionForReturnDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseConditionalExpression/CSharpUseConditionalExpressionForReturnDiagnosticAnalyzer.cs index f3102a1b3e141..4562648667351 100644 --- a/src/Analyzers/CSharp/Analyzers/UseConditionalExpression/CSharpUseConditionalExpressionForReturnDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseConditionalExpression/CSharpUseConditionalExpressionForReturnDiagnosticAnalyzer.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.LanguageService; +using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.UseConditionalExpression; namespace Microsoft.CodeAnalysis.CSharp.UseConditionalExpression @@ -21,5 +22,24 @@ public CSharpUseConditionalExpressionForReturnDiagnosticAnalyzer() protected override ISyntaxFacts GetSyntaxFacts() => CSharpSyntaxFacts.Instance; + + protected override bool IsStatementSupported(IOperation statement) + { + // Return statements wrapped in an unsafe, checked or unchecked block are not supported + // because having these enclosing blocks makes it difficult or impossible to convert + // the blocks to expressions + return !IsWrappedByCheckedOrUnsafe(statement); + } + + private static bool IsWrappedByCheckedOrUnsafe(IOperation statement) + { + if (statement is not IReturnOperation { Parent: IBlockOperation block }) + return false; + + if (block.Syntax.Parent is UnsafeStatementSyntax or CheckedStatementSyntax) + return true; + + return false; + } } } diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs b/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs index 3e262e4d85e12..160b935861b28 100644 --- a/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs +++ b/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordEngine.cs @@ -85,30 +85,7 @@ private static async Task ConvertToPositionalRecordAsync( var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); // first see if we need to re-order our primary constructor parameters. - var propertiesToAssign = positionalParameterInfos.SelectAsArray(info => info.Symbol); - var primaryConstructor = typeDeclaration.Members - .OfType() - .FirstOrDefault(constructor => - { - var constructorSymbol = (IMethodSymbol)semanticModel - .GetRequiredDeclaredSymbol(constructor, cancellationToken); - var constructorOperation = (IConstructorBodyOperation)semanticModel - .GetRequiredOperation(constructor, cancellationToken); - // We want to make sure that each type in the parameter list corresponds - // to exactly one positional parameter type, but they don't need to be in the same order. - // We can't use something like set equality because some parameter types may be duplicate. - // So, we order the types in a consistent way (by name) and then compare the lists of types. - return constructorSymbol.Parameters.SelectAsArray(parameter => parameter.Type) - .OrderBy(type => type.Name) - .SequenceEqual(propertiesToAssign.SelectAsArray(s => s.Type) - .OrderBy(type => type.Name), - SymbolEqualityComparer.Default) && - // make sure that we do all the correct assignments. There may be multiple constructors - // that meet the parameter condition but only one actually assigns all properties. - // If successful, we set propertiesToAssign in the order of the parameters. - ConvertToRecordHelpers.IsSimplePrimaryConstructor( - constructorOperation, ref propertiesToAssign, constructorSymbol.Parameters); - }); + var (primaryConstructor, propertiesToAssign) = TryFindPrimaryConstructor(); var solutionEditor = new SolutionEditor(document.Project.Solution); // we must refactor usages first because usages can appear within the class definition and @@ -174,14 +151,14 @@ await RefactorInitializersAsync(type, solutionEditor, propertiesToAssign, cancel } else { - var constructorSymbol = (IMethodSymbol)semanticModel - .GetRequiredDeclaredSymbol(constructor, cancellationToken); - var constructorOperation = (IConstructorBodyOperation)semanticModel - .GetRequiredOperation(constructor, cancellationToken); + var constructorSymbol = semanticModel.GetRequiredDeclaredSymbol(constructor, cancellationToken); + var constructorOperation = (IConstructorBodyOperation?)semanticModel.GetOperation(constructor, cancellationToken); + if (constructorOperation is null) + continue; // check for copy constructor - if (constructorSymbol.Parameters.Length == 1 && - constructorSymbol.Parameters[0].Type.Equals(type)) + if (constructorSymbol is { Parameters: [{ Type: var parameterType }] } && + parameterType.Equals(type)) { if (ConvertToRecordHelpers.IsSimpleCopyConstructor( constructorOperation, expectedFields, constructorSymbol.Parameters.First())) @@ -352,6 +329,47 @@ await RefactorInitializersAsync(type, solutionEditor, propertiesToAssign, cancel propertiesToAddAsParams, recordKeyword, constructorTrivia, baseList)); return solutionEditor.GetChangedSolution(); + + (ConstructorDeclarationSyntax? constructor, ImmutableArray propertiesToAssign) TryFindPrimaryConstructor() + { + var propertiesToAssign = positionalParameterInfos.SelectAsArray(info => info.Symbol); + var orderedPropertyTypesToAssign = propertiesToAssign.SelectAsArray(s => s.Type).OrderBy(type => type.Name); + + foreach (var member in typeDeclaration.Members) + { + if (member is not ConstructorDeclarationSyntax constructor) + continue; + + var constructorSymbol = semanticModel.GetRequiredDeclaredSymbol(constructor, cancellationToken); + var constructorOperation = (IConstructorBodyOperation?)semanticModel.GetOperation(constructor, cancellationToken); + if (constructorOperation is null) + continue; + + // We want to make sure that each type in the parameter list corresponds + // to exactly one positional parameter type, but they don't need to be in the same order. + // We can't use something like set equality because some parameter types may be duplicate. + // So, we order the types in a consistent way (by name) and then compare the lists of types. + var orderedParameterTypes = constructorSymbol.Parameters + .SelectAsArray(parameter => parameter.Type) + .OrderBy(type => type.Name); + + if (!orderedParameterTypes.SequenceEqual(orderedPropertyTypesToAssign)) + continue; + + // make sure that we do all the correct assignments. There may be multiple constructors + // that meet the parameter condition but only one actually assigns all properties. + // If successful, we set propertiesToAssign in the order of the parameters. + if (!ConvertToRecordHelpers.IsSimplePrimaryConstructor( + constructorOperation, propertiesToAssign, constructorSymbol.Parameters, out var orderedPropertiesToAssign)) + { + continue; + } + + return (constructor, orderedPropertiesToAssign); + } + + return (null, propertiesToAssign); + } } private static RecordDeclarationSyntax CreateRecordDeclaration( diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordHelpers.cs b/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordHelpers.cs index 4a56e1a6eb8cf..d35aaf94132cb 100644 --- a/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordHelpers.cs +++ b/src/Analyzers/CSharp/CodeFixes/ConvertToRecord/ConvertToRecordHelpers.cs @@ -181,9 +181,11 @@ internal static bool IsDefaultNotEqualsOperator( /// Whether the constructor body matches the pattern described public static bool IsSimplePrimaryConstructor( IConstructorBodyOperation operation, - ref ImmutableArray properties, - ImmutableArray parameters) + ImmutableArray properties, + ImmutableArray parameters, + out ImmutableArray orderedProperties) { + orderedProperties = default; if (GetBlockOfMethodBody(operation) is not { Operations.Length: int opLength } || opLength != properties.Length) { @@ -194,25 +196,25 @@ public static bool IsSimplePrimaryConstructor( assignment => (assignment as IParameterReferenceOperation)?.Parameter); // we must assign to all the properties (keys) and use all the parameters (values) - if (assignmentValues.Keys.SetEquals(properties) && - assignmentValues.Values.SetEquals(parameters)) + if (!assignmentValues.Keys.SetEquals(properties) || + !assignmentValues.Values.SetEquals(parameters)) { - // order properties in order of the parameters that they were assigned to - // e.g if we originally have Properties: [int Y, int X] - // and constructor: - // public C(int x, int y) - // { - // X = x; - // Y = y; - // } - // then we would re-order the properties to: [int X, int Y] - properties = properties - .OrderBy(property => parameters.IndexOf(assignmentValues[property])) - .AsImmutable(); - return true; + return false; } - return false; + // order properties in order of the parameters that they were assigned to + // e.g if we originally have Properties: [int Y, int X] + // and constructor: + // public C(int x, int y) + // { + // X = x; + // Y = y; + // } + // then we would re-order the properties to: [int X, int Y] + orderedProperties = properties + .OrderBy(property => parameters.IndexOf(assignmentValues[property])) + .AsImmutable(); + return true; } /// diff --git a/src/Analyzers/CSharp/CodeFixes/RemoveUnreachableCode/CSharpRemoveUnreachableCodeCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/RemoveUnreachableCode/CSharpRemoveUnreachableCodeCodeFixProvider.cs index 761747101e9d2..87a5ec0c765e2 100644 --- a/src/Analyzers/CSharp/CodeFixes/RemoveUnreachableCode/CSharpRemoveUnreachableCodeCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/RemoveUnreachableCode/CSharpRemoveUnreachableCodeCodeFixProvider.cs @@ -9,89 +9,86 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Extensions; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Extensions; -namespace Microsoft.CodeAnalysis.CSharp.RemoveUnreachableCode -{ - [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveUnreachableCode), Shared] - internal sealed class CSharpRemoveUnreachableCodeCodeFixProvider : SyntaxEditorBasedCodeFixProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpRemoveUnreachableCodeCodeFixProvider() - { - } +namespace Microsoft.CodeAnalysis.CSharp.RemoveUnreachableCode; - public override ImmutableArray FixableDiagnosticIds { get; } = - [IDEDiagnosticIds.RemoveUnreachableCodeDiagnosticId]; +[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveUnreachableCode), Shared] +[method: ImportingConstructor] +[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] +internal sealed class CSharpRemoveUnreachableCodeCodeFixProvider() : SyntaxEditorBasedCodeFixProvider +{ + public override ImmutableArray FixableDiagnosticIds { get; } = + [IDEDiagnosticIds.RemoveUnreachableCodeDiagnosticId]; - public override Task RegisterCodeFixesAsync(CodeFixContext context) - { - var diagnostic = context.Diagnostics[0]; + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + var diagnostic = context.Diagnostics[0]; - // Only the first reported unreacha ble line will have a squiggle. On that line, make the - // code action normal priority as the user is likely bringing up the lightbulb to fix the - // squiggle. On all the other lines make the code action low priority as it's definitely - // helpful, but shouldn't interfere with anything else the uesr is doing. - var priority = IsSubsequentSection(diagnostic) - ? CodeActionPriority.Low - : CodeActionPriority.Default; + // Only the first reported unreachable line will have a squiggle. On that line, make the code action normal + // priority as the user is likely bringing up the lightbulb to fix the squiggle. On all the other lines + // make the code action low priority as it's definitely helpful, but shouldn't interfere with anything else + // the user is doing. + var priority = IsSubsequentSection(diagnostic) + ? CodeActionPriority.Low + : CodeActionPriority.Default; - RegisterCodeFix(context, CSharpCodeFixesResources.Remove_unreachable_code, nameof(CSharpCodeFixesResources.Remove_unreachable_code), priority); + RegisterCodeFix(context, CSharpCodeFixesResources.Remove_unreachable_code, nameof(CSharpCodeFixesResources.Remove_unreachable_code), priority); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic) - => !IsSubsequentSection(diagnostic); + protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic) + => !IsSubsequentSection(diagnostic); - private static bool IsSubsequentSection(Diagnostic diagnostic) - => diagnostic.Properties.ContainsKey(CSharpRemoveUnreachableCodeDiagnosticAnalyzer.IsSubsequentSection); + private static bool IsSubsequentSection(Diagnostic diagnostic) + => diagnostic.Properties.ContainsKey(CSharpRemoveUnreachableCodeDiagnosticAnalyzer.IsSubsequentSection); - protected override Task FixAllAsync( - Document document, - ImmutableArray diagnostics, - SyntaxEditor editor, - CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + protected override Task FixAllAsync( + Document document, + ImmutableArray diagnostics, + SyntaxEditor editor, + CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + { + foreach (var diagnostic in diagnostics) { - foreach (var diagnostic in diagnostics) - { - var firstUnreachableStatementLocation = diagnostic.AdditionalLocations[0]; - var firstUnreachableStatement = (StatementSyntax)firstUnreachableStatementLocation.FindNode(getInnermostNodeForTie: true, cancellationToken); + var firstUnreachableStatementLocation = diagnostic.AdditionalLocations[0]; + var firstUnreachableStatement = CSharpRemoveUnreachableCodeDiagnosticAnalyzer.TryGetContainingStatement( + firstUnreachableStatementLocation.FindNode(getInnermostNodeForTie: true, cancellationToken)); - RemoveStatement(editor, firstUnreachableStatement); + if (firstUnreachableStatement is null) + continue; - var sections = RemoveUnreachableCodeHelpers.GetSubsequentUnreachableSections(firstUnreachableStatement); - foreach (var section in sections) + RemoveStatement(editor, firstUnreachableStatement); + + var sections = RemoveUnreachableCodeHelpers.GetSubsequentUnreachableSections(firstUnreachableStatement); + foreach (var section in sections) + { + foreach (var statement in section) { - foreach (var statement in section) - { - RemoveStatement(editor, statement); - } + RemoveStatement(editor, statement); } } + } - return Task.CompletedTask; + return Task.CompletedTask; - // Local function - static void RemoveStatement(SyntaxEditor editor, SyntaxNode statement) + // Local function + static void RemoveStatement(SyntaxEditor editor, SyntaxNode statement) + { + if (statement.Parent?.Kind() + is not SyntaxKind.Block + and not SyntaxKind.SwitchSection + and not SyntaxKind.GlobalStatement) { - if (statement.Parent?.Kind() - is not SyntaxKind.Block - and not SyntaxKind.SwitchSection - and not SyntaxKind.GlobalStatement) - { - editor.ReplaceNode(statement, SyntaxFactory.Block()); - } - else - { - editor.RemoveNode(statement, SyntaxRemoveOptions.KeepUnbalancedDirectives); - } + editor.ReplaceNode(statement, SyntaxFactory.Block()); + } + else + { + editor.RemoveNode(statement, SyntaxRemoveOptions.KeepUnbalancedDirectives); } } } diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForArrayCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForArrayCodeFixProvider.cs index 244ff82e960b1..92645fb39b683 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForArrayCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForArrayCodeFixProvider.cs @@ -105,11 +105,11 @@ ImmutableArray> GetMatches( { ImplicitArrayCreationExpressionSyntax arrayCreation => CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer.TryGetMatches( - semanticModel, arrayCreation, expressionType, allowInterfaceConversion: true, cancellationToken, out _), + semanticModel, arrayCreation, expressionType, allowSemanticsChange: true, cancellationToken, out _), ArrayCreationExpressionSyntax arrayCreation => CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer.TryGetMatches( - semanticModel, arrayCreation, expressionType, allowInterfaceConversion: true, cancellationToken, out _), + semanticModel, arrayCreation, expressionType, allowSemanticsChange: true, cancellationToken, out _), // We validated this is unreachable in the caller. _ => throw ExceptionUtilities.Unreachable(), diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderCodeFixProvider.cs index b1772af67fd78..9f30628e78fad 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForBuilderCodeFixProvider.cs @@ -45,7 +45,7 @@ protected override async Task FixAsync( { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var expressionType = semanticModel.Compilation.ExpressionOfTType(); - if (AnalyzeInvocation(semanticModel, invocationExpression, expressionType, allowInterfaceConversion: true, cancellationToken) is not { } analysisResult) + if (AnalyzeInvocation(semanticModel, invocationExpression, expressionType, allowSemanticsChange: true, cancellationToken) is not { } analysisResult) return; // We want to replace the final invocation (`builder.ToImmutable()`) with `new()`. That way we can call into diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs index 51689dbc60541..00d7b1232c2a7 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs @@ -55,7 +55,7 @@ protected override async Task FixAsync( var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var expressionType = semanticModel.Compilation.ExpressionOfTType(); - if (AnalyzeInvocation(text, state, invocationExpression, expressionType, allowInterfaceConversion: true, addMatches: true, cancellationToken) is not { } analysisResult) + if (AnalyzeInvocation(text, state, invocationExpression, expressionType, allowSemanticsChange: true, addMatches: true, cancellationToken) is not { } analysisResult) return; // We want to replace `new[] { 1, 2, 3 }.Concat(x).Add(y).ToArray()` with the new collection expression. To do diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocCodeFixProvider.cs index f812610c896bf..2299e93e4e016 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForStackAllocCodeFixProvider.cs @@ -84,7 +84,7 @@ ImmutableArray> GetMatches() // be added to the collection expression. StackAllocArrayCreationExpressionSyntax arrayCreation => CSharpUseCollectionExpressionForStackAllocDiagnosticAnalyzer.TryGetMatches( - semanticModel, arrayCreation, expressionType, allowInterfaceConversion: true, cancellationToken), + semanticModel, arrayCreation, expressionType, allowSemanticsChange: true, cancellationToken), // We validated this is unreachable in the caller. _ => throw ExceptionUtilities.Unreachable(), diff --git a/src/Analyzers/CSharp/CodeFixes/UsePrimaryConstructor/CSharpUsePrimaryConstructorCodeFixProvider_DocComments.cs b/src/Analyzers/CSharp/CodeFixes/UsePrimaryConstructor/CSharpUsePrimaryConstructorCodeFixProvider_DocComments.cs index b1f9c1f823994..9769bf3150aaf 100644 --- a/src/Analyzers/CSharp/CodeFixes/UsePrimaryConstructor/CSharpUsePrimaryConstructorCodeFixProvider_DocComments.cs +++ b/src/Analyzers/CSharp/CodeFixes/UsePrimaryConstructor/CSharpUsePrimaryConstructorCodeFixProvider_DocComments.cs @@ -57,7 +57,7 @@ private static bool IsXmlElement(XmlNodeSyntax node, string name, [NotNullWhen(t private static XmlElementSyntax ConvertXmlElementName(XmlElementSyntax xmlElement, string name) { return xmlElement.ReplaceTokens( - new[] { xmlElement.StartTag.Name.LocalName, xmlElement.EndTag.Name.LocalName }, + [xmlElement.StartTag.Name.LocalName, xmlElement.EndTag.Name.LocalName], (token, _) => Identifier(name).WithTriviaFrom(token)); } diff --git a/src/Analyzers/CSharp/Tests/AddBraces/AddBracesFixAllTests.cs b/src/Analyzers/CSharp/Tests/AddBraces/AddBracesFixAllTests.cs index 728f56c078bb8..e38aa7cc8d6dd 100644 --- a/src/Analyzers/CSharp/Tests/AddBraces/AddBracesFixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/AddBraces/AddBracesFixAllTests.cs @@ -17,31 +17,31 @@ public partial class AddBracesTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocument1() { - var input = @" -class Program1 -{ - static void Main() - { - {|FixAllInDocument:if|} (true) if (true) return; - } -} -"; - - var expected = @" -class Program1 -{ - static void Main() - { - if (true) - { - if (true) - { - return; - } - } - } -} -"; + var input = """ + class Program1 + { + static void Main() + { + {|FixAllInDocument:if|} (true) if (true) return; + } + } + """; + + var expected = """ + class Program1 + { + static void Main() + { + if (true) + { + if (true) + { + return; + } + } + } + } + """; await TestInRegularAndScriptAsync(input, expected); } @@ -50,31 +50,31 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocument2() { - var input = @" -class Program1 -{ - static void Main() - { - if (true) {|FixAllInDocument:if|} (true) return; - } -} -"; - - var expected = @" -class Program1 -{ - static void Main() - { - if (true) - { - if (true) - { - return; - } - } - } -} -"; + var input = """ + class Program1 + { + static void Main() + { + if (true) {|FixAllInDocument:if|} (true) return; + } + } + """; + + var expected = """ + class Program1 + { + static void Main() + { + if (true) + { + if (true) + { + return; + } + } + } + } + """; await TestInRegularAndScriptAsync(input, expected); } @@ -83,84 +83,86 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocument() { - var input = @" - - - -class Program1 -{ - static void Main() - { - {|FixAllInDocument:if|} (true) return; - if (true) return; - } -} - - -class Program2 -{ - static void Main() - { - if (true) return; - } -} - - - - -class Program3 -{ - static void Main() - { - if (true) return; - } -} - - -"; - - var expected = @" - - - -class Program1 -{ - static void Main() - { - if (true) - { - return; - } - - if (true) - { - return; - } - } -} - - -class Program2 -{ - static void Main() - { - if (true) return; - } -} - - - - -class Program3 -{ - static void Main() - { - if (true) return; - } -} - - -"; + var input = """ + + + + class Program1 + { + static void Main() + { + {|FixAllInDocument:if|} (true) return; + if (true) return; + } + } + + + class Program2 + { + static void Main() + { + if (true) return; + } + } + + + + + class Program3 + { + static void Main() + { + if (true) return; + } + } + + + + """; + + var expected = """ + + + + class Program1 + { + static void Main() + { + if (true) + { + return; + } + + if (true) + { + return; + } + } + } + + + class Program2 + { + static void Main() + { + if (true) return; + } + } + + + + + class Program3 + { + static void Main() + { + if (true) return; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -169,81 +171,83 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProject() { - var input = @" - - - -class Program1 -{ - static void Main() - { - {|FixAllInProject:if|} (true) return; - } -} - - -class Program2 -{ - static void Main() - { - if (true) return; - } -} - - - - -class Program3 -{ - static void Main() - { - if (true) return; - } -} - - -"; - - var expected = @" - - - -class Program1 -{ - static void Main() - { - if (true) - { - return; - } - } -} - - -class Program2 -{ - static void Main() - { - if (true) - { - return; - } - } -} - - - - -class Program3 -{ - static void Main() - { - if (true) return; - } -} - - -"; + var input = """ + + + + class Program1 + { + static void Main() + { + {|FixAllInProject:if|} (true) return; + } + } + + + class Program2 + { + static void Main() + { + if (true) return; + } + } + + + + + class Program3 + { + static void Main() + { + if (true) return; + } + } + + + + """; + + var expected = """ + + + + class Program1 + { + static void Main() + { + if (true) + { + return; + } + } + } + + + class Program2 + { + static void Main() + { + if (true) + { + return; + } + } + } + + + + + class Program3 + { + static void Main() + { + if (true) return; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -252,84 +256,86 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution() { - var input = @" - - - -class Program1 -{ - static void Main() - { - {|FixAllInSolution:if|} (true) return; - } -} - - -class Program2 -{ - static void Main() - { - if (true) return; - } -} - - - - -class Program3 -{ - static void Main() - { - if (true) return; - } -} - - -"; - - var expected = @" - - - -class Program1 -{ - static void Main() - { - if (true) - { - return; - } - } -} - - -class Program2 -{ - static void Main() - { - if (true) - { - return; - } - } -} - - - - -class Program3 -{ - static void Main() - { - if (true) - { - return; - } - } -} - - -"; + var input = """ + + + + class Program1 + { + static void Main() + { + {|FixAllInSolution:if|} (true) return; + } + } + + + class Program2 + { + static void Main() + { + if (true) return; + } + } + + + + + class Program3 + { + static void Main() + { + if (true) return; + } + } + + + + """; + + var expected = """ + + + + class Program1 + { + static void Main() + { + if (true) + { + return; + } + } + } + + + class Program2 + { + static void Main() + { + if (true) + { + return; + } + } + } + + + + + class Program3 + { + static void Main() + { + if (true) + { + return; + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -338,65 +344,67 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingMember() { - var input = @" -class Program1 -{ - static void Main() - { - {|FixAllInContainingMember:if|} (true) if (true) return; - - if (false) if (false) return; - } - - void OtherMethod() - { - if (true) if (true) return; - } -} - -class OtherType -{ - void OtherMethod() - { - if (true) if (true) return; - } -}"; - - var expected = @" -class Program1 -{ - static void Main() - { - if (true) - { - if (true) - { - return; - } - } - - if (false) - { - if (false) - { - return; - } - } - } - - void OtherMethod() - { - if (true) if (true) return; - } -} - -class OtherType -{ - void OtherMethod() - { - if (true) if (true) return; - } -}"; + var input = """ + class Program1 + { + static void Main() + { + {|FixAllInContainingMember:if|} (true) if (true) return; + + if (false) if (false) return; + } + + void OtherMethod() + { + if (true) if (true) return; + } + } + + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + """; + + var expected = """ + class Program1 + { + static void Main() + { + if (true) + { + if (true) + { + return; + } + } + + if (false) + { + if (false) + { + return; + } + } + } + + void OtherMethod() + { + if (true) if (true) return; + } + } + + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + """; await TestInRegularAndScriptAsync(input, expected); } @@ -405,71 +413,73 @@ void OtherMethod() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingType_AcrossSingleFile() { - var input = @" -class Program1 -{ - static void Main() - { - {|FixAllInContainingType:if|} (true) if (true) return; - - if (false) if (false) return; - } - - void OtherMethod() - { - if (true) if (true) return; - } -} - -class OtherType -{ - void OtherMethod() - { - if (true) if (true) return; - } -}"; - - var expected = @" -class Program1 -{ - static void Main() - { - if (true) - { - if (true) - { - return; - } - } - - if (false) - { - if (false) - { - return; - } - } - } - - void OtherMethod() - { - if (true) - { - if (true) - { - return; - } - } - } -} - -class OtherType -{ - void OtherMethod() - { - if (true) if (true) return; - } -}"; + var input = """ + class Program1 + { + static void Main() + { + {|FixAllInContainingType:if|} (true) if (true) return; + + if (false) if (false) return; + } + + void OtherMethod() + { + if (true) if (true) return; + } + } + + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + """; + + var expected = """ + class Program1 + { + static void Main() + { + if (true) + { + if (true) + { + return; + } + } + + if (false) + { + if (false) + { + return; + } + } + } + + void OtherMethod() + { + if (true) + { + if (true) + { + return; + } + } + } + } + + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + """; await TestInRegularAndScriptAsync(input, expected); } @@ -478,109 +488,111 @@ void OtherMethod() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingType_AcrossMultipleFiles() { - var input = @" - - - -partial class Program1 -{ - static void Main() - { - {|FixAllInContainingType:if|} (true) if (true) return; - - if (false) if (false) return; - } - - void OtherMethod() - { - if (true) if (true) return; - } -} - - -partial class Program1 -{ - void OtherFileMethod() - { - if (true) if (true) return; - } -} - - -class Program2 -{ - void OtherTypeMethod() - { - if (true) if (true) return; - } -} - - -"; - - var expected = @" - - - -partial class Program1 -{ - static void Main() - { - if (true) - { - if (true) - { - return; - } - } - - if (false) - { - if (false) - { - return; - } - } - } - - void OtherMethod() - { - if (true) - { - if (true) - { - return; - } - } - } -} - - -partial class Program1 -{ - void OtherFileMethod() - { - if (true) - { - if (true) - { - return; - } - } - } -} - - -class Program2 -{ - void OtherTypeMethod() - { - if (true) if (true) return; - } -} - - -"; + var input = """ + + + + partial class Program1 + { + static void Main() + { + {|FixAllInContainingType:if|} (true) if (true) return; + + if (false) if (false) return; + } + + void OtherMethod() + { + if (true) if (true) return; + } + } + + + partial class Program1 + { + void OtherFileMethod() + { + if (true) if (true) return; + } + } + + + class Program2 + { + void OtherTypeMethod() + { + if (true) if (true) return; + } + } + + + + """; + + var expected = """ + + + + partial class Program1 + { + static void Main() + { + if (true) + { + if (true) + { + return; + } + } + + if (false) + { + if (false) + { + return; + } + } + } + + void OtherMethod() + { + if (true) + { + if (true) + { + return; + } + } + } + } + + + partial class Program1 + { + void OtherFileMethod() + { + if (true) + { + if (true) + { + return; + } + } + } + } + + + class Program2 + { + void OtherTypeMethod() + { + if (true) if (true) return; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -593,43 +605,45 @@ void OtherTypeMethod() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingMemberAndType_TopLevelStatements(string fixAllScope) { - var input = $@" -{{|{fixAllScope}:if|}} (true) if (true) return; - -if (false) if (false) return; - -class OtherType -{{ - void OtherMethod() - {{ - if (true) if (true) return; - }} -}}"; - - var expected = @" -if (true) -{ - if (true) - { - return; - } -} - -if (false) -{ - if (false) - { - return; - } -} - -class OtherType -{ - void OtherMethod() - { - if (true) if (true) return; - } -}"; + var input = $$""" + {|{{fixAllScope}}:if|} (true) if (true) return; + + if (false) if (false) return; + + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + """; + + var expected = """ + if (true) + { + if (true) + { + return; + } + } + + if (false) + { + if (false) + { + return; + } + } + + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + """; await TestInRegularAndScriptAsync(input, expected); } @@ -640,53 +654,55 @@ void OtherMethod() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingMemberAndType_TopLevelStatements_02(string fixAllScope) { - var input = $@" -using System; - -{{|{fixAllScope}:if|}} (true) if (true) return; - -if (false) if (false) return; - -namespace N -{{ - class OtherType - {{ - void OtherMethod() - {{ - if (true) if (true) return; - }} - }} -}}"; - - var expected = @" -using System; - -if (true) -{ - if (true) - { - return; - } -} - -if (false) -{ - if (false) - { - return; - } -} - -namespace N -{ - class OtherType - { - void OtherMethod() - { - if (true) if (true) return; - } - } -}"; + var input = $$""" + using System; + + {|{{fixAllScope}}:if|} (true) if (true) return; + + if (false) if (false) return; + + namespace N + { + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + } + """; + + var expected = """ + using System; + + if (true) + { + if (true) + { + return; + } + } + + if (false) + { + if (false) + { + return; + } + } + + namespace N + { + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + } + """; await TestInRegularAndScriptAsync(input, expected); } @@ -698,18 +714,19 @@ void OtherMethod() public async Task TestFixAllInContainingMemberAndType_TopLevelStatements_ErrorCase(string fixAllScope) { // Error case: Global statements should precede non-global statements. - var input = $@" -class OtherType -{{ - void OtherMethod() - {{ - if (true) if (true) return; - }} -}} - -{{|{fixAllScope}:if|}} (true) if (true) return; - -if (false) if (false) return;"; + var input = $$""" + class OtherType + { + void OtherMethod() + { + if (true) if (true) return; + } + } + + {|{{fixAllScope}}:if|} (true) if (true) return; + + if (false) if (false) return; + """; await TestMissingInRegularAndScriptAsync(input); } diff --git a/src/Analyzers/CSharp/Tests/AddExplicitCast/AddExplicitCastTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/AddExplicitCast/AddExplicitCastTests_FixAllTests.cs index 4fa7a78a871bc..0fde7f0e6bb3f 100644 --- a/src/Analyzers/CSharp/Tests/AddExplicitCast/AddExplicitCastTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/AddExplicitCast/AddExplicitCastTests_FixAllTests.cs @@ -19,1117 +19,573 @@ public partial class AddExplicitCastTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task CS0266TestFixAllInDocument() { - var input = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - Base ReturnBase(Derived d) - { - Base b = new Base(); - return b; - } - - Derived ReturnDerived(Base b) - { - return b; - } - - ReturnDerived() ]]> - { - Base b; - yield return b; - } - - ReturnDerived() - { - Base b; - return b; - } ]]> - - M() ]]> - { - Base b; - return b; - } - - Derived ReturnDerived2(Base b) - { - return ReturnBase(); - } - - Derived Foo() - { - func = d => d; ]]> - Base b; - return func(b); - } - public Program1() - { - Base b; - Derived d = {|FixAllInDocument:b|}; - d = new Base() { }; - - Derived d2 = ReturnBase(); - Derived d2 = ReturnBase(b); - - Test t = new Test(); - t.D = b; - t.d = b; - d = t.B; - - foo = d => d; ]]> - - foo2 = d => d; ]]> - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - Derived2 returnDerived2_1() { - return new Derived1(); - } - - Derived2 returnDerived2_2() { - return new Test(); - } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Derived2 derived2 = b1; - derived2 = b3; - Base2 base2 = b1; - derived2 = d1; - Derived2 d2 = new Test(); - } -} - - - - -public class Program3 -{ - class Base { } - class Derived : Base { } - class Derived2 : Derived { } - - Derived2 returnD2(Base b) - { - Derived d; - return d = b; - } -} - - -"; - - var expected = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - Base ReturnBase(Derived d) - { - Base b = new Base(); - return b; - } - - Derived ReturnDerived(Base b) - { - return (Derived)b; - } - - ReturnDerived() ]]> - { - Base b; - yield return (Derived)b; - } - - ReturnDerived() - { - Base b; - return (IEnumerable)b; - } ]]> - - M() ]]> - { - Base b; - return (Derived)b; - } - - Derived ReturnDerived2(Base b) - { - return (Derived)ReturnBase(); - } - - Derived Foo() - { - func = d => d; ]]> - Base b; - return (Derived)func(b); - } - public Program1() - { - Base b; - Derived d = (Derived)b; - d = new Base() { }; - - Derived d2 = (Derived)ReturnBase(); - Derived d2 = ReturnBase(b); - - Test t = new Test(); - t.D = (Derived)b; - t.d = b; - d = (Derived)t.B; - - foo = d => (Derived)d; ]]> - - foo2 = d => d; ]]> - d2 = (Derived)foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - Derived2 returnDerived2_1() { - return new Derived1(); - } - - Derived2 returnDerived2_2() { - return new Test(); - } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Derived2 derived2 = b1; - derived2 = b3; - Base2 base2 = b1; - derived2 = d1; - Derived2 d2 = new Test(); - } -} - - - - -public class Program3 -{ - class Base { } - class Derived : Base { } - class Derived2 : Derived { } - - Derived2 returnD2(Base b) - { - Derived d; - return d = b; - } -} - - -"; - - await TestInRegularAndScriptAsync(input, expected); - } - - [Fact] - [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] - [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] - public async Task CS0266TestFixAllInProject() - { - var input = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - Base ReturnBase(Derived d) - { - Base b = new Base(); - return b; - } - - Derived ReturnDerived(Base b) - { - return b; - } - - ReturnDerived() ]]> - { - Base b; - yield return b; - } - - ReturnDerived() - { - Base b; - return b; - } ]]> - - M() ]]> - { - Base b; - return b; - } - - Derived ReturnDerived2(Base b) - { - return ReturnBase(); - } - - Derived Foo() - { - func = d => d; ]]> - Base b; - return func(b); - } - public Program1() - { - Base b; - Derived d = {|FixAllInProject:b|}; - d = new Base() { }; - - Derived d2 = ReturnBase(); - Derived d2 = ReturnBase(b); - - Test t = new Test(); - t.D = b; - t.d = b; - d = t.B; - - foo = d => d; ]]> - - foo2 = d => d; ]]> - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - Derived2 returnDerived2_1() { - return new Derived1(); - } - - Derived2 returnDerived2_2() { - return new Test(); - } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Derived2 derived2 = b1; - derived2 = b3; - Base2 base2 = b1; - derived2 = d1; - Derived2 d2 = new Test(); - } -} - - - - -public class Program3 -{ - class Base { } - class Derived : Base { } - class Derived2 : Derived { } - - Derived2 returnD2(Base b) - { - Derived d; - return d = b; - } -} - - -"; - - var expected = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - Base ReturnBase(Derived d) - { - Base b = new Base(); - return b; - } - - Derived ReturnDerived(Base b) - { - return (Derived)b; - } - - ReturnDerived() ]]> - { - Base b; - yield return (Derived)b; - } - - ReturnDerived() - { - Base b; - return (IEnumerable)b; - } ]]> - - M() ]]> - { - Base b; - return (Derived)b; - } - - Derived ReturnDerived2(Base b) - { - return (Derived)ReturnBase(); - } - - Derived Foo() - { - func = d => d; ]]> - Base b; - return (Derived)func(b); - } - public Program1() - { - Base b; - Derived d = (Derived)b; - d = new Base() { }; - - Derived d2 = (Derived)ReturnBase(); - Derived d2 = ReturnBase(b); - - Test t = new Test(); - t.D = (Derived)b; - t.d = b; - d = (Derived)t.B; - - foo = d => (Derived)d; ]]> - - foo2 = d => d; ]]> - d2 = (Derived)foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - Derived2 returnDerived2_1() { - return new Derived1(); - } - - Derived2 returnDerived2_2() { - return (Derived2)new Test(); - } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Derived2 derived2 = (Derived2)b1; - derived2 = (Derived2)b3; - Base2 base2 = (Base2)b1; - derived2 = (Derived2)d1; - Derived2 d2 = (Derived2)new Test(); - } -} - - - - -public class Program3 -{ - class Base { } - class Derived : Base { } - class Derived2 : Derived { } - - Derived2 returnD2(Base b) - { - Derived d; - return d = b; - } -} - - -"; - - await TestInRegularAndScriptAsync(input, expected); - } - - [Fact] - [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] - [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] - public async Task CS0266TestFixAllInSolution() - { - var input = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - Base ReturnBase(Derived d) - { - Base b = new Base(); - return b; - } - - Derived ReturnDerived(Base b) - { - return b; - } - - ReturnDerived() ]]> - { - Base b; - yield return b; - } - - ReturnDerived() - { - Base b; - return b; - } ]]> - - M() ]]> - { - Base b; - return b; - } - - Derived ReturnDerived2(Base b) - { - return ReturnBase(); - } - - Derived Foo() - { - func = d => d; ]]> - Base b; - return func(b); - } - public Program1() - { - Base b; - Derived d = {|FixAllInSolution:b|}; - d = new Base() { }; - - Derived d2 = ReturnBase(); - Derived d2 = ReturnBase(b); - - Test t = new Test(); - t.D = b; - t.d = b; - d = t.B; - - foo = d => d; ]]> - - foo2 = d => d; ]]> - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - Derived2 returnDerived2_1() { - return new Derived1(); - } - - Derived2 returnDerived2_2() { - return new Test(); - } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Derived2 derived2 = b1; - derived2 = b3; - Base2 base2 = b1; - derived2 = d1; - Derived2 d2 = new Test(); - } -} - - - - -public class Program3 -{ - class Base { } - class Derived : Base { } - class Derived2 : Derived { } - - Derived2 returnD2(Base b) - { - Derived d; - return d = b; - } -} - - -"; - - var expected = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - Base ReturnBase(Derived d) - { - Base b = new Base(); - return b; - } - - Derived ReturnDerived(Base b) - { - return (Derived)b; - } - - ReturnDerived() ]]> - { - Base b; - yield return (Derived)b; - } - - ReturnDerived() - { - Base b; - return (IEnumerable)b; - } ]]> - - M() ]]> - { - Base b; - return (Derived)b; - } - - Derived ReturnDerived2(Base b) - { - return (Derived)ReturnBase(); - } - - Derived Foo() - { - func = d => d; ]]> - Base b; - return (Derived)func(b); - } - public Program1() - { - Base b; - Derived d = (Derived)b; - d = new Base() { }; - - Derived d2 = (Derived)ReturnBase(); - Derived d2 = ReturnBase(b); - - Test t = new Test(); - t.D = (Derived)b; - t.d = b; - d = (Derived)t.B; - - foo = d => (Derived)d; ]]> - - foo2 = d => d; ]]> - d2 = (Derived)foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - Derived2 returnDerived2_1() { - return new Derived1(); - } - - Derived2 returnDerived2_2() { - return (Derived2)new Test(); - } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Derived2 derived2 = (Derived2)b1; - derived2 = (Derived2)b3; - Base2 base2 = (Base2)b1; - derived2 = (Derived2)d1; - Derived2 d2 = (Derived2)new Test(); - } -} - - - - -public class Program3 -{ - class Base { } - class Derived : Base { } - class Derived2 : Derived { } - - Derived2 returnD2(Base b) - { - Derived d; - return (Derived2)(d = (Derived)b); - } -} - - -"; - - await TestInRegularAndScriptAsync(input, expected); - } - - [Fact] - [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] - [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] - public async Task CS1503TestFixAllInDocument() - { - var input = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Test(Derived derived) - { - d = derived; - B = derived; - } - - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - - public void testing(Derived d) { } - private void testing(Base b) { } - } - - class Test2 : Test - { - public Test2(Base b) : base(b) { } - } - - class Test3 - { - public Test3(Derived b) { } - public Test3(int i, Base b) : this(b) { } - - public void testing(int i, Derived d) { } - private void testing(int i, Base d) { } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - void PassDerived(Derived d) { } - void PassDerived(int i, Derived d) { } - - public Program1() - { - Base b; - Derived d = b; - - PassDerived({|FixAllInDocument:b|}); - PassDerived(ReturnBase()); - PassDerived(1, b); - PassDerived(1, ReturnBase()); - - list = new List(); ]]> - list.Add(b); - - Test t = new Test(); - t.testing(b); - - foo2 = d => d; ]]> - Derived d2 = foo2(b); - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - - - -class Program3 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - -"; - - var expected = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -public class Program1 -{ - class Base { } - class Derived : Base { } + var input = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + Base ReturnBase(Derived d) + { + Base b = new Base(); + return b; + } + + Derived ReturnDerived(Base b) + { + return b; + } + + ReturnDerived() ]]> + { + Base b; + yield return b; + } + + ReturnDerived() + { + Base b; + return b; + } ]]> + + M() ]]> + { + Base b; + return b; + } + + Derived ReturnDerived2(Base b) + { + return ReturnBase(); + } + + Derived Foo() + { + func = d => d; ]]> + Base b; + return func(b); + } + public Program1() + { + Base b; + Derived d = {|FixAllInDocument:b|}; + d = new Base() { }; + + Derived d2 = ReturnBase(); + Derived d2 = ReturnBase(b); + + Test t = new Test(); + t.D = b; + t.d = b; + d = t.B; + + foo = d => d; ]]> + + foo2 = d => d; ]]> + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + Derived2 returnDerived2_1() { + return new Derived1(); + } + + Derived2 returnDerived2_2() { + return new Test(); + } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Derived2 derived2 = b1; + derived2 = b3; + Base2 base2 = b1; + derived2 = d1; + Derived2 d2 = new Test(); + } + } + + + + + public class Program3 + { + class Base { } + class Derived : Base { } + class Derived2 : Derived { } + + Derived2 returnD2(Base b) + { + Derived d; + return d = b; + } + } + + + + """; + + var expected = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + Base ReturnBase(Derived d) + { + Base b = new Base(); + return b; + } + + Derived ReturnDerived(Base b) + { + return (Derived)b; + } + + ReturnDerived() ]]> + { + Base b; + yield return (Derived)b; + } + + ReturnDerived() + { + Base b; + return (IEnumerable)b; + } ]]> + + M() ]]> + { + Base b; + return (Derived)b; + } + + Derived ReturnDerived2(Base b) + { + return (Derived)ReturnBase(); + } + + Derived Foo() + { + func = d => d; ]]> + Base b; + return (Derived)func(b); + } + public Program1() + { + Base b; + Derived d = (Derived)b; + d = new Base() { }; + + Derived d2 = (Derived)ReturnBase(); + Derived d2 = ReturnBase(b); + + Test t = new Test(); + t.D = (Derived)b; + t.d = b; + d = (Derived)t.B; + + foo = d => (Derived)d; ]]> + + foo2 = d => d; ]]> + d2 = (Derived)foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + Derived2 returnDerived2_1() { + return new Derived1(); + } + + Derived2 returnDerived2_2() { + return new Test(); + } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Derived2 derived2 = b1; + derived2 = b3; + Base2 base2 = b1; + derived2 = d1; + Derived2 d2 = new Test(); + } + } + + + + + public class Program3 + { + class Base { } + class Derived : Base { } + class Derived2 : Derived { } + + Derived2 returnD2(Base b) + { + Derived d; + return d = b; + } + } + + + + """; - class Test - { - private Derived d; - private Base b; - public Test(Derived derived) - { - d = derived; - B = derived; + await TestInRegularAndScriptAsync(input, expected); } - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - - public void testing(Derived d) { } - private void testing(Base b) { } - } - - class Test2 : Test - { - public Test2(Base b) : base((Derived)b) { } - } - - class Test3 - { - public Test3(Derived b) { } - public Test3(int i, Base b) : this((Derived)b) { } - - public void testing(int i, Derived d) { } - private void testing(int i, Base d) { } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - void PassDerived(Derived d) { } - void PassDerived(int i, Derived d) { } - - public Program1() - { - Base b; - Derived d = b; - - PassDerived((Derived)b); - PassDerived((Derived)ReturnBase()); - PassDerived(1, (Derived)b); - PassDerived(1, (Derived)ReturnBase()); - - list = new List(); ]]> - list.Add((Derived)b); - - Test t = new Test(); - t.testing((Derived)b); - - foo2 = d => d; ]]> - Derived d2 = foo2((Derived)b); - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - - - -class Program3 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - -"; + [Fact] + [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] + [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] + public async Task CS0266TestFixAllInProject() + { + var input = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + Base ReturnBase(Derived d) + { + Base b = new Base(); + return b; + } + + Derived ReturnDerived(Base b) + { + return b; + } + + ReturnDerived() ]]> + { + Base b; + yield return b; + } + + ReturnDerived() + { + Base b; + return b; + } ]]> + + M() ]]> + { + Base b; + return b; + } + + Derived ReturnDerived2(Base b) + { + return ReturnBase(); + } + + Derived Foo() + { + func = d => d; ]]> + Base b; + return func(b); + } + public Program1() + { + Base b; + Derived d = {|FixAllInProject:b|}; + d = new Base() { }; + + Derived d2 = ReturnBase(); + Derived d2 = ReturnBase(b); + + Test t = new Test(); + t.D = b; + t.d = b; + d = t.B; + + foo = d => d; ]]> + + foo2 = d => d; ]]> + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + Derived2 returnDerived2_1() { + return new Derived1(); + } + + Derived2 returnDerived2_2() { + return new Test(); + } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Derived2 derived2 = b1; + derived2 = b3; + Base2 base2 = b1; + derived2 = d1; + Derived2 d2 = new Test(); + } + } + + + + + public class Program3 + { + class Base { } + class Derived : Base { } + class Derived2 : Derived { } + + Derived2 returnD2(Base b) + { + Derived d; + return d = b; + } + } + + + + """; + + var expected = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + Base ReturnBase(Derived d) + { + Base b = new Base(); + return b; + } + + Derived ReturnDerived(Base b) + { + return (Derived)b; + } + + ReturnDerived() ]]> + { + Base b; + yield return (Derived)b; + } + + ReturnDerived() + { + Base b; + return (IEnumerable)b; + } ]]> + + M() ]]> + { + Base b; + return (Derived)b; + } + + Derived ReturnDerived2(Base b) + { + return (Derived)ReturnBase(); + } + + Derived Foo() + { + func = d => d; ]]> + Base b; + return (Derived)func(b); + } + public Program1() + { + Base b; + Derived d = (Derived)b; + d = new Base() { }; + + Derived d2 = (Derived)ReturnBase(); + Derived d2 = ReturnBase(b); + + Test t = new Test(); + t.D = (Derived)b; + t.d = b; + d = (Derived)t.B; + + foo = d => (Derived)d; ]]> + + foo2 = d => d; ]]> + d2 = (Derived)foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + Derived2 returnDerived2_1() { + return new Derived1(); + } + + Derived2 returnDerived2_2() { + return (Derived2)new Test(); + } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Derived2 derived2 = (Derived2)b1; + derived2 = (Derived2)b3; + Base2 base2 = (Base2)b1; + derived2 = (Derived2)d1; + Derived2 d2 = (Derived2)new Test(); + } + } + + + + + public class Program3 + { + class Base { } + class Derived : Base { } + class Derived2 : Derived { } + + Derived2 returnD2(Base b) + { + Derived d; + return d = b; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -1137,339 +593,551 @@ private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) [Fact] [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] - public async Task CS1503TestFixAllInProject() + public async Task CS0266TestFixAllInSolution() { - var input = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -public class Program1 -{ - class Base { } - class Derived : Base { } + var input = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + Base ReturnBase(Derived d) + { + Base b = new Base(); + return b; + } + + Derived ReturnDerived(Base b) + { + return b; + } + + ReturnDerived() ]]> + { + Base b; + yield return b; + } + + ReturnDerived() + { + Base b; + return b; + } ]]> + + M() ]]> + { + Base b; + return b; + } + + Derived ReturnDerived2(Base b) + { + return ReturnBase(); + } + + Derived Foo() + { + func = d => d; ]]> + Base b; + return func(b); + } + public Program1() + { + Base b; + Derived d = {|FixAllInSolution:b|}; + d = new Base() { }; + + Derived d2 = ReturnBase(); + Derived d2 = ReturnBase(b); + + Test t = new Test(); + t.D = b; + t.d = b; + d = t.B; + + foo = d => d; ]]> + + foo2 = d => d; ]]> + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + Derived2 returnDerived2_1() { + return new Derived1(); + } + + Derived2 returnDerived2_2() { + return new Test(); + } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Derived2 derived2 = b1; + derived2 = b3; + Base2 base2 = b1; + derived2 = d1; + Derived2 d2 = new Test(); + } + } + + + + + public class Program3 + { + class Base { } + class Derived : Base { } + class Derived2 : Derived { } + + Derived2 returnD2(Base b) + { + Derived d; + return d = b; + } + } + + + + """; + + var expected = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + Base ReturnBase(Derived d) + { + Base b = new Base(); + return b; + } + + Derived ReturnDerived(Base b) + { + return (Derived)b; + } + + ReturnDerived() ]]> + { + Base b; + yield return (Derived)b; + } + + ReturnDerived() + { + Base b; + return (IEnumerable)b; + } ]]> + + M() ]]> + { + Base b; + return (Derived)b; + } + + Derived ReturnDerived2(Base b) + { + return (Derived)ReturnBase(); + } + + Derived Foo() + { + func = d => d; ]]> + Base b; + return (Derived)func(b); + } + public Program1() + { + Base b; + Derived d = (Derived)b; + d = new Base() { }; + + Derived d2 = (Derived)ReturnBase(); + Derived d2 = ReturnBase(b); + + Test t = new Test(); + t.D = (Derived)b; + t.d = b; + d = (Derived)t.B; + + foo = d => (Derived)d; ]]> + + foo2 = d => d; ]]> + d2 = (Derived)foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + Derived2 returnDerived2_1() { + return new Derived1(); + } + + Derived2 returnDerived2_2() { + return (Derived2)new Test(); + } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Derived2 derived2 = (Derived2)b1; + derived2 = (Derived2)b3; + Base2 base2 = (Base2)b1; + derived2 = (Derived2)d1; + Derived2 d2 = (Derived2)new Test(); + } + } + + + + + public class Program3 + { + class Base { } + class Derived : Base { } + class Derived2 : Derived { } + + Derived2 returnD2(Base b) + { + Derived d; + return (Derived2)(d = (Derived)b); + } + } + + + + """; - class Test - { - private Derived d; - private Base b; - public Test(Derived derived) - { - d = derived; - B = derived; + await TestInRegularAndScriptAsync(input, expected); } - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - - public void testing(Derived d) { } - private void testing(Base b) { } - } - - class Test2 : Test - { - public Test2(Base b) : base(b) { } - } - - class Test3 - { - public Test3(Derived b) { } - public Test3(int i, Base b) : this(b) { } - - public void testing(int i, Derived d) { } - private void testing(int i, Base d) { } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - void PassDerived(Derived d) { } - void PassDerived(int i, Derived d) { } - - public Program1() - { - Base b; - Derived d = b; - - PassDerived({|FixAllInProject:b|}); - PassDerived(ReturnBase()); - PassDerived(1, b); - PassDerived(1, ReturnBase()); - - list = new List(); ]]> - list.Add(b); - - Test t = new Test(); - t.testing(b); - - foo2 = d => d; ]]> - Derived d2 = foo2(b); - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived1(Test t) { return new Derived1(); } - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - void Foo4(int i, string j, Derived1 d) { } - void Foo4(string j, int i, Derived1 d) { } - - void Foo5(string j, int i, Derived2 d, int x = 1) { } - - void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { } - - void Foo6(Derived1 d, params Derived2[] d2list) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - - Foo2(b1); - - Foo3(b1); - - Foo4(1, """", b1); - Foo4(i: 1, j: """", b1); // one operation, fix - - Foo5("""", 1, b1); // multiple operations, no fix-all - - Foo5(d: b1, i: 1, j: """", x: 1); // all arguments out of order - match - Foo5(1, """", x: 1, d: b1); // part of arguments out of order - mismatch - - Foo5(1, """", d: b1, b2, b3, d1); // part of arguments out of order - mismatch - Foo5("""", 1, d: b1, b2, b3, d1); // part of arguments out of order - match - - var d2list = new Derived2[] { }; - Foo5(d2list: d2list, j: """", i: 1, d: b2); - var d1list = new Derived1[] { }; - Foo5(d2list: d1list, j: """", i: 1, d: b2); - - Foo6(b1); - - Foo6(new Test()); // params is optional, object creation can be cast with explicit cast operator - Foo6(new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator - Foo6(new Derived1(), new Test()); - } -} - - - - -class Program3 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - -"; - - var expected = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Test(Derived derived) + [Fact] + [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] + [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] + public async Task CS1503TestFixAllInDocument() { - d = derived; - B = derived; - } - - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - - public void testing(Derived d) { } - private void testing(Base b) { } - } - - class Test2 : Test - { - public Test2(Base b) : base((Derived)b) { } - } - - class Test3 - { - public Test3(Derived b) { } - public Test3(int i, Base b) : this((Derived)b) { } - - public void testing(int i, Derived d) { } - private void testing(int i, Base d) { } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - void PassDerived(Derived d) { } - void PassDerived(int i, Derived d) { } - - public Program1() - { - Base b; - Derived d = b; - - PassDerived((Derived)b); - PassDerived((Derived)ReturnBase()); - PassDerived(1, (Derived)b); - PassDerived(1, (Derived)ReturnBase()); - - list = new List(); ]]> - list.Add((Derived)b); - - Test t = new Test(); - t.testing((Derived)b); - - foo2 = d => d; ]]> - Derived d2 = foo2((Derived)b); - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - class Test - { - static public explicit operator Derived1(Test t) { return new Derived1(); } - static public explicit operator Derived2(Test t) { return new Derived2(); } - } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - void Foo4(int i, string j, Derived1 d) { } - void Foo4(string j, int i, Derived1 d) { } - - void Foo5(string j, int i, Derived2 d, int x = 1) { } - - void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { } - - void Foo6(Derived1 d, params Derived2[] d2list) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1((Derived2)b1); - Foo1((Derived2)d1); - - Foo2((Base2)b1); - - Foo3((Derived2)b1); - - Foo4(1, """", (Derived1)b1); - Foo4(i: 1, j: """", (Derived1)b1); // one operation, fix - - Foo5("""", 1, b1); // multiple operations, no fix-all - - Foo5(d: (Derived2)b1, i: 1, j: """", x: 1); // all arguments out of order - match - Foo5(1, """", x: 1, d: b1); // part of arguments out of order - mismatch - - Foo5(1, """", d: b1, b2, b3, d1); // part of arguments out of order - mismatch - Foo5("""", 1, d: (Derived1)b1, (Derived2)b2, (Derived2)b3, (Derived2)d1); // part of arguments out of order - match - - var d2list = new Derived2[] { }; - Foo5(d2list: d2list, j: """", i: 1, d: (Derived1)b2); - var d1list = new Derived1[] { }; - Foo5(d2list: (Derived2[])d1list, j: """", i: 1, d: (Derived1)b2); - - Foo6((Derived1)b1); - - Foo6((Derived1)new Test()); // params is optional, object creation can be cast with explicit cast operator - Foo6((Derived1)new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator - Foo6(new Derived1(), (Derived2)new Test()); - } -} - - - - -class Program3 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - -"; + var input = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Test(Derived derived) + { + d = derived; + B = derived; + } + + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + + public void testing(Derived d) { } + private void testing(Base b) { } + } + + class Test2 : Test + { + public Test2(Base b) : base(b) { } + } + + class Test3 + { + public Test3(Derived b) { } + public Test3(int i, Base b) : this(b) { } + + public void testing(int i, Derived d) { } + private void testing(int i, Base d) { } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + void PassDerived(Derived d) { } + void PassDerived(int i, Derived d) { } + + public Program1() + { + Base b; + Derived d = b; + + PassDerived({|FixAllInDocument:b|}); + PassDerived(ReturnBase()); + PassDerived(1, b); + PassDerived(1, ReturnBase()); + + list = new List(); ]]> + list.Add(b); + + Test t = new Test(); + t.testing(b); + + foo2 = d => d; ]]> + Derived d2 = foo2(b); + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + + class Program3 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + """; + + var expected = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Test(Derived derived) + { + d = derived; + B = derived; + } + + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + + public void testing(Derived d) { } + private void testing(Base b) { } + } + + class Test2 : Test + { + public Test2(Base b) : base((Derived)b) { } + } + + class Test3 + { + public Test3(Derived b) { } + public Test3(int i, Base b) : this((Derived)b) { } + + public void testing(int i, Derived d) { } + private void testing(int i, Base d) { } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + void PassDerived(Derived d) { } + void PassDerived(int i, Derived d) { } + + public Program1() + { + Base b; + Derived d = b; + + PassDerived((Derived)b); + PassDerived((Derived)ReturnBase()); + PassDerived(1, (Derived)b); + PassDerived(1, (Derived)ReturnBase()); + + list = new List(); ]]> + list.Add((Derived)b); + + Test t = new Test(); + t.testing((Derived)b); + + foo2 = d => d; ]]> + Derived d2 = foo2((Derived)b); + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + + class Program3 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -1477,265 +1145,609 @@ private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) [Fact] [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] - public async Task CS1503TestFixAllInSolution() + public async Task CS1503TestFixAllInProject() { - var input = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -public class Program1 -{ - class Base { } - class Derived : Base { } + var input = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Test(Derived derived) + { + d = derived; + B = derived; + } + + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + + public void testing(Derived d) { } + private void testing(Base b) { } + } + + class Test2 : Test + { + public Test2(Base b) : base(b) { } + } + + class Test3 + { + public Test3(Derived b) { } + public Test3(int i, Base b) : this(b) { } + + public void testing(int i, Derived d) { } + private void testing(int i, Base d) { } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + void PassDerived(Derived d) { } + void PassDerived(int i, Derived d) { } + + public Program1() + { + Base b; + Derived d = b; + + PassDerived({|FixAllInProject:b|}); + PassDerived(ReturnBase()); + PassDerived(1, b); + PassDerived(1, ReturnBase()); + + list = new List(); ]]> + list.Add(b); + + Test t = new Test(); + t.testing(b); + + foo2 = d => d; ]]> + Derived d2 = foo2(b); + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived1(Test t) { return new Derived1(); } + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + void Foo4(int i, string j, Derived1 d) { } + void Foo4(string j, int i, Derived1 d) { } + + void Foo5(string j, int i, Derived2 d, int x = 1) { } + + void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { } + + void Foo6(Derived1 d, params Derived2[] d2list) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + + Foo2(b1); + + Foo3(b1); + + Foo4(1, "", b1); + Foo4(i: 1, j: "", b1); // one operation, fix + + Foo5("", 1, b1); // multiple operations, no fix-all + + Foo5(d: b1, i: 1, j: "", x: 1); // all arguments out of order - match + Foo5(1, "", x: 1, d: b1); // part of arguments out of order - mismatch + + Foo5(1, "", d: b1, b2, b3, d1); // part of arguments out of order - mismatch + Foo5("", 1, d: b1, b2, b3, d1); // part of arguments out of order - match + + var d2list = new Derived2[] { }; + Foo5(d2list: d2list, j: "", i: 1, d: b2); + var d1list = new Derived1[] { }; + Foo5(d2list: d1list, j: "", i: 1, d: b2); + + Foo6(b1); + + Foo6(new Test()); // params is optional, object creation can be cast with explicit cast operator + Foo6(new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator + Foo6(new Derived1(), new Test()); + } + } + + + + + class Program3 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + """; + + var expected = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Test(Derived derived) + { + d = derived; + B = derived; + } + + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + + public void testing(Derived d) { } + private void testing(Base b) { } + } + + class Test2 : Test + { + public Test2(Base b) : base((Derived)b) { } + } + + class Test3 + { + public Test3(Derived b) { } + public Test3(int i, Base b) : this((Derived)b) { } + + public void testing(int i, Derived d) { } + private void testing(int i, Base d) { } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + void PassDerived(Derived d) { } + void PassDerived(int i, Derived d) { } + + public Program1() + { + Base b; + Derived d = b; + + PassDerived((Derived)b); + PassDerived((Derived)ReturnBase()); + PassDerived(1, (Derived)b); + PassDerived(1, (Derived)ReturnBase()); + + list = new List(); ]]> + list.Add((Derived)b); + + Test t = new Test(); + t.testing((Derived)b); + + foo2 = d => d; ]]> + Derived d2 = foo2((Derived)b); + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + class Test + { + static public explicit operator Derived1(Test t) { return new Derived1(); } + static public explicit operator Derived2(Test t) { return new Derived2(); } + } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + void Foo4(int i, string j, Derived1 d) { } + void Foo4(string j, int i, Derived1 d) { } + + void Foo5(string j, int i, Derived2 d, int x = 1) { } + + void Foo5(string j, int i, Derived1 d, params Derived2[] d2list) { } + + void Foo6(Derived1 d, params Derived2[] d2list) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1((Derived2)b1); + Foo1((Derived2)d1); + + Foo2((Base2)b1); + + Foo3((Derived2)b1); + + Foo4(1, "", (Derived1)b1); + Foo4(i: 1, j: "", (Derived1)b1); // one operation, fix + + Foo5("", 1, b1); // multiple operations, no fix-all + + Foo5(d: (Derived2)b1, i: 1, j: "", x: 1); // all arguments out of order - match + Foo5(1, "", x: 1, d: b1); // part of arguments out of order - mismatch + + Foo5(1, "", d: b1, b2, b3, d1); // part of arguments out of order - mismatch + Foo5("", 1, d: (Derived1)b1, (Derived2)b2, (Derived2)b3, (Derived2)d1); // part of arguments out of order - match + + var d2list = new Derived2[] { }; + Foo5(d2list: d2list, j: "", i: 1, d: (Derived1)b2); + var d1list = new Derived1[] { }; + Foo5(d2list: (Derived2[])d1list, j: "", i: 1, d: (Derived1)b2); + + Foo6((Derived1)b1); + + Foo6((Derived1)new Test()); // params is optional, object creation can be cast with explicit cast operator + Foo6((Derived1)new Test(), new Derived1()); // object creation cannot be cast without explicit cast operator + Foo6(new Derived1(), (Derived2)new Test()); + } + } + + + + + class Program3 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + """; - class Test - { - private Derived d; - private Base b; - public Test(Derived derived) - { - d = derived; - B = derived; + await TestInRegularAndScriptAsync(input, expected); } - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - - public void testing(Derived d) { } - private void testing(Base b) { } - } - - class Test2 : Test - { - public Test2(Base b) : base(b) { } - } - - class Test3 - { - public Test3(Derived b) { } - public Test3(int i, Base b) : this(b) { } - - public void testing(int i, Derived d) { } - private void testing(int i, Base d) { } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - void PassDerived(Derived d) { } - void PassDerived(int i, Derived d) { } - - public Program1() - { - Base b; - Derived d = b; - - PassDerived({|FixAllInSolution:b|}); - PassDerived(ReturnBase()); - PassDerived(1, b); - PassDerived(1, ReturnBase()); - - list = new List(); ]]> - list.Add(b); - - Test t = new Test(); - t.testing(b); - - foo2 = d => d; ]]> - Derived d2 = foo2(b); - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1(b1); - Foo1(d1); - Foo2(b1); - Foo3(b1); - } -} - - - - -class Program3 -{ - interface Base { } - class Derived1 : Base { } - class Derived2 : Derived1 { } - - class Test - { - public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all - Test(string s, Derived1 d, int i) { } - Test(string s, Derived2 d, int i) { } - } - - void Foo(Derived1 d, int a, int b, params int[] list) { } - void Foo(Derived2 d, params int[] list) { } - - - private void M2(Base b, Derived1 d1, Derived2 d2) - { - Foo(b, 1, 2); // 2 operations, no fix in fix-all - var intlist = new int[] { }; - Foo(b, 1, 2, list: intlist); // 2 operations - } -} - - -"; - - var expected = @" - - - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -public class Program1 -{ - class Base { } - class Derived : Base { } - - class Test - { - private Derived d; - private Base b; - public Test(Derived derived) + [Fact] + [Trait(Traits.Feature, Traits.Features.CodeActionsAddExplicitCast)] + [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] + public async Task CS1503TestFixAllInSolution() { - d = derived; - B = derived; - } - - public Derived D { get => d; set => d = value; } - public Base B { get => b; set => b = value; } - - public void testing(Derived d) { } - private void testing(Base b) { } - } - - class Test2 : Test - { - public Test2(Base b) : base((Derived)b) { } - } - - class Test3 - { - public Test3(Derived b) { } - public Test3(int i, Base b) : this((Derived)b) { } - - public void testing(int i, Derived d) { } - private void testing(int i, Base d) { } - } - - Base ReturnBase() - { - Base b = new Base(); - return b; - } - - void PassDerived(Derived d) { } - void PassDerived(int i, Derived d) { } - - public Program1() - { - Base b; - Derived d = b; - - PassDerived((Derived)b); - PassDerived((Derived)ReturnBase()); - PassDerived(1, (Derived)b); - PassDerived(1, (Derived)ReturnBase()); - - list = new List(); ]]> - list.Add((Derived)b); - - Test t = new Test(); - t.testing((Derived)b); - - foo2 = d => d; ]]> - Derived d2 = foo2((Derived)b); - d2 = foo2(d); - } -} - - -public class Program2 -{ - interface Base1 { } - interface Base2 : Base1 { } - interface Base3 { } - class Derived1 : Base2, Base3 { } - class Derived2 : Derived1 { } - - void Foo1(Derived2 b) { } - void Foo2(Base2 b) { } - - void Foo3(Derived2 b1) { } - void Foo3(int i) { } - - private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) - { - Foo1((Derived2)b1); - Foo1((Derived2)d1); - Foo2((Base2)b1); - Foo3((Derived2)b1); - } -} - - - - -class Program3 -{ - interface Base { } - class Derived1 : Base { } - class Derived2 : Derived1 { } - - class Test - { - public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all - Test(string s, Derived1 d, int i) { } - Test(string s, Derived2 d, int i) { } - } - - void Foo(Derived1 d, int a, int b, params int[] list) { } - void Foo(Derived2 d, params int[] list) { } - - - private void M2(Base b, Derived1 d1, Derived2 d2) - { - Foo(b, 1, 2); // 2 operations, no fix in fix-all - var intlist = new int[] { }; - Foo(b, 1, 2, list: intlist); // 2 operations - } -} - - -"; + var input = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Test(Derived derived) + { + d = derived; + B = derived; + } + + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + + public void testing(Derived d) { } + private void testing(Base b) { } + } + + class Test2 : Test + { + public Test2(Base b) : base(b) { } + } + + class Test3 + { + public Test3(Derived b) { } + public Test3(int i, Base b) : this(b) { } + + public void testing(int i, Derived d) { } + private void testing(int i, Base d) { } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + void PassDerived(Derived d) { } + void PassDerived(int i, Derived d) { } + + public Program1() + { + Base b; + Derived d = b; + + PassDerived({|FixAllInSolution:b|}); + PassDerived(ReturnBase()); + PassDerived(1, b); + PassDerived(1, ReturnBase()); + + list = new List(); ]]> + list.Add(b); + + Test t = new Test(); + t.testing(b); + + foo2 = d => d; ]]> + Derived d2 = foo2(b); + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1(b1); + Foo1(d1); + Foo2(b1); + Foo3(b1); + } + } + + + + + class Program3 + { + interface Base { } + class Derived1 : Base { } + class Derived2 : Derived1 { } + + class Test + { + public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all + Test(string s, Derived1 d, int i) { } + Test(string s, Derived2 d, int i) { } + } + + void Foo(Derived1 d, int a, int b, params int[] list) { } + void Foo(Derived2 d, params int[] list) { } + + + private void M2(Base b, Derived1 d1, Derived2 d2) + { + Foo(b, 1, 2); // 2 operations, no fix in fix-all + var intlist = new int[] { }; + Foo(b, 1, 2, list: intlist); // 2 operations + } + } + + + + """; + + var expected = """ + + + + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + public class Program1 + { + class Base { } + class Derived : Base { } + + class Test + { + private Derived d; + private Base b; + public Test(Derived derived) + { + d = derived; + B = derived; + } + + public Derived D { get => d; set => d = value; } + public Base B { get => b; set => b = value; } + + public void testing(Derived d) { } + private void testing(Base b) { } + } + + class Test2 : Test + { + public Test2(Base b) : base((Derived)b) { } + } + + class Test3 + { + public Test3(Derived b) { } + public Test3(int i, Base b) : this((Derived)b) { } + + public void testing(int i, Derived d) { } + private void testing(int i, Base d) { } + } + + Base ReturnBase() + { + Base b = new Base(); + return b; + } + + void PassDerived(Derived d) { } + void PassDerived(int i, Derived d) { } + + public Program1() + { + Base b; + Derived d = b; + + PassDerived((Derived)b); + PassDerived((Derived)ReturnBase()); + PassDerived(1, (Derived)b); + PassDerived(1, (Derived)ReturnBase()); + + list = new List(); ]]> + list.Add((Derived)b); + + Test t = new Test(); + t.testing((Derived)b); + + foo2 = d => d; ]]> + Derived d2 = foo2((Derived)b); + d2 = foo2(d); + } + } + + + public class Program2 + { + interface Base1 { } + interface Base2 : Base1 { } + interface Base3 { } + class Derived1 : Base2, Base3 { } + class Derived2 : Derived1 { } + + void Foo1(Derived2 b) { } + void Foo2(Base2 b) { } + + void Foo3(Derived2 b1) { } + void Foo3(int i) { } + + private void M2(Base1 b1, Base2 b2, Base3 b3, Derived1 d1, Derived2 d2) + { + Foo1((Derived2)b1); + Foo1((Derived2)d1); + Foo2((Base2)b1); + Foo3((Derived2)b1); + } + } + + + + + class Program3 + { + interface Base { } + class Derived1 : Base { } + class Derived2 : Derived1 { } + + class Test + { + public Test(string s, Base b, int i, params object[] list) : this(d: b, s: s, i: i) { } // 2 operations, no fix in fix-all + Test(string s, Derived1 d, int i) { } + Test(string s, Derived2 d, int i) { } + } + + void Foo(Derived1 d, int a, int b, params int[] list) { } + void Foo(Derived2 d, params int[] list) { } + + + private void M2(Base b, Derived1 d1, Derived2 d2) + { + Foo(b, 1, 2); // 2 operations, no fix in fix-all + var intlist = new int[] { }; + Foo(b, 1, 2, list: intlist); // 2 operations + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } diff --git a/src/Analyzers/CSharp/Tests/AddInheritdoc/AddInheritdocTests.cs b/src/Analyzers/CSharp/Tests/AddInheritdoc/AddInheritdocTests.cs index 88c99f96681a1..5c9f8ed81ac36 100644 --- a/src/Analyzers/CSharp/Tests/AddInheritdoc/AddInheritdocTests.cs +++ b/src/Analyzers/CSharp/Tests/AddInheritdoc/AddInheritdocTests.cs @@ -72,18 +72,19 @@ public override void M() { } public async Task DoNotOfferOnNotOverridenMethod(string methodDefintion) { await TestMissingAsync( - $@" -/// Some doc. -public class BaseClass -{{ - /// Some doc. - public virtual void M() {{ }} -}} -/// Some doc. -public class Derived: BaseClass -{{ - {methodDefintion} -}}"); + $$""" + /// Some doc. + public class BaseClass + { + /// Some doc. + public virtual void M() { } + } + /// Some doc. + public class Derived: BaseClass + { + {{methodDefintion}} + } + """); } [Fact] diff --git a/src/Analyzers/CSharp/Tests/AddParameter/AddParameterTests.cs b/src/Analyzers/CSharp/Tests/AddParameter/AddParameterTests.cs index a3a29183940e9..5a0895da35505 100644 --- a/src/Analyzers/CSharp/Tests/AddParameter/AddParameterTests.cs +++ b/src/Analyzers/CSharp/Tests/AddParameter/AddParameterTests.cs @@ -2928,17 +2928,17 @@ public static class IsExternalInit { } [Fact] public async Task Test_PrimaryConstructor_Class() { - await TestInRegularAndScriptAsync(@" -var b = ""B""; -var r = [|new R(1, b)|]; + await TestInRegularAndScriptAsync(""" + var b = "B"; + var r = [|new R(1, b)|]; -class R(int A); -", @" -var b = ""B""; -var r = new R(1, b); + class R(int A); + """, """ + var b = "B"; + var r = new R(1, b); -class R(int A, string b); -", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp12)); + class R(int A, string b); + """, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp12)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/54408")] @@ -2970,17 +2970,17 @@ public static class IsExternalInit { } [Fact] public async Task Test_PrimaryConstructor_Struct() { - await TestInRegularAndScriptAsync(@" -var b = ""B""; -var r = [|new R(1, b)|]; + await TestInRegularAndScriptAsync(""" + var b = "B"; + var r = [|new R(1, b)|]; -struct R(int A); -", @" -var b = ""B""; -var r = new R(1, b); + struct R(int A); + """, """ + var b = "B"; + var r = new R(1, b); -struct R(int A, string b); -", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp12)); + struct R(int A, string b); + """, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp12)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/56952")] @@ -3002,13 +3002,15 @@ record Test(string V); [Fact] public async Task TestNamingConventions_PrimaryConstructor_Class() { - await TestInRegularAndScript1Async(@"[|new Test(""repro"")|]; + await TestInRegularAndScript1Async(""" + [|new Test("repro")|]; -class Test(); -", @"new Test(""repro""); + class Test(); + """, """ + new Test("repro"); -class Test(string v); -"); + class Test(string v); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/56952")] @@ -3030,13 +3032,15 @@ record struct Test(string V); [Fact] public async Task TestNamingConventions_PrimaryConstructor_Struct() { - await TestInRegularAndScript1Async(@"[|new Test(""repro"")|]; + await TestInRegularAndScript1Async(""" + [|new Test("repro")|]; -struct Test(); -", @"new Test(""repro""); + struct Test(); + """, """ + new Test("repro"); -struct Test(string v); -"); + struct Test(string v); + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/61715")] diff --git a/src/Analyzers/CSharp/Tests/AssignOutParameters/AssignOutParametersAtStartTests.cs b/src/Analyzers/CSharp/Tests/AssignOutParameters/AssignOutParametersAtStartTests.cs index b579f99f76e1d..105523a8fa3e9 100644 --- a/src/Analyzers/CSharp/Tests/AssignOutParameters/AssignOutParametersAtStartTests.cs +++ b/src/Analyzers/CSharp/Tests/AssignOutParameters/AssignOutParametersAtStartTests.cs @@ -27,13 +27,15 @@ public class AssignOutParametersAtStartTests public async Task TestForSimpleReturn() { // Handled by other fixer - var code = @"class C -{ - char M(out int i) - { - {|CS0177:return 'a';|} - } -}"; + var code = """ + class C + { + char M(out int i) + { + {|CS0177:return 'a';|} + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -42,42 +44,48 @@ char M(out int i) public async Task TestForSwitchSectionReturn() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(out int i) - { - switch (0) - { - default: - {|CS0177:return 'a';|} - } - } -}", -@"class C -{ - char M(out int i) - { - i = 0; - switch (0) - { - default: - return 'a'; - } - } -}"); + """ + class C + { + char M(out int i) + { + switch (0) + { + default: + {|CS0177:return 'a';|} + } + } + } + """, + """ + class C + { + char M(out int i) + { + i = 0; + switch (0) + { + default: + return 'a'; + } + } + } + """); } [Fact] public async Task TestMissingWhenVariableAssigned() { - var code = @"class C -{ - char M(out int i) - { - i = 0; - return 'a'; - } -}"; + var code = """ + class C + { + char M(out int i) + { + i = 0; + return 'a'; + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -86,46 +94,52 @@ char M(out int i) public async Task TestWhenNotAssignedThroughAllPaths1() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i) - { - if (b) - i = 1; - - {|CS0177:return 'a';|} - } -}", -@"class C -{ - char M(bool b, out int i) - { - i = 0; - if (b) - i = 1; - - return 'a'; - } -}"); + """ + class C + { + char M(bool b, out int i) + { + if (b) + i = 1; + + {|CS0177:return 'a';|} + } + } + """, + """ + class C + { + char M(bool b, out int i) + { + i = 0; + if (b) + i = 1; + + return 'a'; + } + } + """); } [Fact] public async Task TestWhenNotAssignedThroughAllPaths2() { // Handled by other fixer - var code = @"class C -{ - bool M(out int i1, out int i2) - { - {|CS0177:return Try(out i1) || Try(out i2);|} - } - - bool Try(out int i) - { - i = 0; - return true; - } -}"; + var code = """ + class C + { + bool M(out int i1, out int i2) + { + {|CS0177:return Try(out i1) || Try(out i2);|} + } + + bool Try(out int i) + { + i = 0; + return true; + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -133,18 +147,20 @@ bool Try(out int i) [Fact] public async Task TestMissingWhenAssignedThroughAllPaths() { - var code = @"class C -{ - char M(bool b, out int i) - { - if (b) - i = 1; - else - i = 2; - - return 'a'; - } -}"; + var code = """ + class C + { + char M(bool b, out int i) + { + if (b) + i = 1; + else + i = 2; + + return 'a'; + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -153,13 +169,15 @@ char M(bool b, out int i) public async Task TestMultiple() { // Handled by other fixer - var code = @"class C -{ - char M(out int i, out string s) - { - {|CS0177:{|CS0177:return 'a';|}|} - } -}"; + var code = """ + class C + { + char M(out int i, out string s) + { + {|CS0177:{|CS0177:return 'a';|}|} + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -168,13 +186,15 @@ char M(out int i, out string s) public async Task TestMultiple_AssignedInReturn1() { // Handled by other fixer - var code = @"class C -{ - string M(out int i, out string s) - { - {|CS0177:return s = """";|} - } -}"; + var code = """ + class C + { + string M(out int i, out string s) + { + {|CS0177:return s = "";|} + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -183,13 +203,15 @@ string M(out int i, out string s) public async Task TestMultiple_AssignedInReturn2() { // Handled by other fixer - var code = @"class C -{ - string M(out int i, out string s) - { - {|CS0177:return (i = 0).ToString();|} - } -}"; + var code = """ + class C + { + string M(out int i, out string s) + { + {|CS0177:return (i = 0).ToString();|} + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -198,93 +220,107 @@ string M(out int i, out string s) public async Task TestNestedReturn() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(out int i) - { - if (true) - { - {|CS0177:return 'a';|} - } - } -}", -@"class C -{ - char M(out int i) - { - i = 0; - if (true) - { - return 'a'; - } - } -}"); + """ + class C + { + char M(out int i) + { + if (true) + { + {|CS0177:return 'a';|} + } + } + } + """, + """ + class C + { + char M(out int i) + { + i = 0; + if (true) + { + return 'a'; + } + } + } + """); } [Fact] public async Task TestNestedReturnNoBlock() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(out int i) - { - if (true) - {|CS0177:return 'a';|} - } -}", -@"class C -{ - char M(out int i) - { - i = 0; - if (true) - return 'a'; - } -}"); + """ + class C + { + char M(out int i) + { + if (true) + {|CS0177:return 'a';|} + } + } + """, + """ + class C + { + char M(out int i) + { + i = 0; + if (true) + return 'a'; + } + } + """); } [Fact] public async Task TestNestedReturnEvenWhenWrittenAfter() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i) - { - if (b) - { - {|CS0177:return 'a';|} - } - - i = 1; - throw null; - } -}", -@"class C -{ - char M(bool b, out int i) - { - i = 0; - if (b) - { - return 'a'; - } - - i = 1; - throw null; - } -}"); + """ + class C + { + char M(bool b, out int i) + { + if (b) + { + {|CS0177:return 'a';|} + } + + i = 1; + throw null; + } + } + """, + """ + class C + { + char M(bool b, out int i) + { + i = 0; + if (b) + { + return 'a'; + } + + i = 1; + throw null; + } + } + """); } [Fact] public async Task TestForExpressionBodyMember() { // Handled by other fixer - var code = @"class C -{ - char M(out int i) => {|CS0177:'a'|}; -}"; + var code = """ + class C + { + char M(out int i) => {|CS0177:'a'|}; + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -293,14 +329,16 @@ public async Task TestForExpressionBodyMember() public async Task TestForLambdaExpressionBody() { // Handled by other fixer - var code = @"class C -{ - delegate char D(out int i); - void X() - { - D d = (out int i) => {|CS0177:'a'|}; - } -}"; + var code = """ + class C + { + delegate char D(out int i); + void X() + { + D d = (out int i) => {|CS0177:'a'|}; + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -309,14 +347,16 @@ void X() public async Task TestMissingForLocalFunctionExpressionBody() { // Handled by other fixer - var code = @"class C -{ - void X() - { - char {|CS0177:D|}(out int i) => 'a'; - D(out _); - } -}"; + var code = """ + class C + { + void X() + { + char {|CS0177:D|}(out int i) => 'a'; + D(out _); + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -325,17 +365,19 @@ void X() public async Task TestForLambdaBlockBody() { // Handled by other fixer - var code = @"class C -{ - delegate char D(out int i); - void X() - { - D d = (out int i) => - { - {|CS0177:return 'a';|} - }; - } -}"; + var code = """ + class C + { + delegate char D(out int i); + void X() + { + D d = (out int i) => + { + {|CS0177:return 'a';|} + }; + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -344,18 +386,20 @@ void X() public async Task TestForLocalFunctionBlockBody() { // Handled by other fixer - var code = @"class C -{ - void X() - { - char D(out int i) - { - {|CS0177:return 'a';|} - } - - D(out _); - } -}"; + var code = """ + class C + { + void X() + { + char D(out int i) + { + {|CS0177:return 'a';|} + } + + D(out _); + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -363,20 +407,22 @@ char D(out int i) [Fact] public async Task TestForOutParamInSinglePath() { - var code = @"class C -{ - char M(bool b, out int i) - { - if (b) - i = 1; - else - SomeMethod(out i); + var code = """ + class C + { + char M(bool b, out int i) + { + if (b) + i = 1; + else + SomeMethod(out i); - return 'a'; - } + return 'a'; + } - void SomeMethod(out int i) => i = 0; -}"; + void SomeMethod(out int i) => i = 0; + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -385,279 +431,303 @@ char M(bool b, out int i) public async Task TestFixAll1() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i, out int j) - { - if (b) - { - {|CS0177:{|CS0177:return 'a';|}|} - } - else - { - {|CS0177:{|CS0177:return 'a';|}|} - } - } -}", -@"class C -{ - char M(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - { - return 'a'; - } - else - { - return 'a'; - } - } -}"); + """ + class C + { + char M(bool b, out int i, out int j) + { + if (b) + { + {|CS0177:{|CS0177:return 'a';|}|} + } + else + { + {|CS0177:{|CS0177:return 'a';|}|} + } + } + } + """, + """ + class C + { + char M(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + { + return 'a'; + } + else + { + return 'a'; + } + } + } + """); } [Fact] public async Task TestFixAll1_MultipleMethods() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i, out int j) - { - if (b) - { - {|CS0177:{|CS0177:return 'a';|}|} - } - else - { - {|CS0177:{|CS0177:return 'a';|}|} - } - } - char N(bool b, out int i, out int j) - { - if (b) - { - {|CS0177:{|CS0177:return 'a';|}|} - } - else - { - {|CS0177:{|CS0177:return 'a';|}|} - } - } -}", -@"class C -{ - char M(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - { - return 'a'; - } - else - { - return 'a'; - } - } - - char N(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - { - return 'a'; - } - else - { - return 'a'; - } - } -}"); + """ + class C + { + char M(bool b, out int i, out int j) + { + if (b) + { + {|CS0177:{|CS0177:return 'a';|}|} + } + else + { + {|CS0177:{|CS0177:return 'a';|}|} + } + } + char N(bool b, out int i, out int j) + { + if (b) + { + {|CS0177:{|CS0177:return 'a';|}|} + } + else + { + {|CS0177:{|CS0177:return 'a';|}|} + } + } + } + """, + """ + class C + { + char M(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + { + return 'a'; + } + else + { + return 'a'; + } + } + + char N(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + { + return 'a'; + } + else + { + return 'a'; + } + } + } + """); } [Fact] public async Task TestFixAll2() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i, out int j) - { - if (b) - {|CS0177:{|CS0177:return 'a';|}|} - else - {|CS0177:{|CS0177:return 'a';|}|} - } -}", -@"class C -{ - char M(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - return 'a'; - else - return 'a'; - } -}"); + """ + class C + { + char M(bool b, out int i, out int j) + { + if (b) + {|CS0177:{|CS0177:return 'a';|}|} + else + {|CS0177:{|CS0177:return 'a';|}|} + } + } + """, + """ + class C + { + char M(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + return 'a'; + else + return 'a'; + } + } + """); } [Fact] public async Task TestFixAll2_MultipleMethods() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i, out int j) - { - if (b) - {|CS0177:{|CS0177:return 'a';|}|} - else - {|CS0177:{|CS0177:return 'a';|}|} - } - char N(bool b, out int i, out int j) - { - if (b) - {|CS0177:{|CS0177:return 'a';|}|} - else - {|CS0177:{|CS0177:return 'a';|}|} - } -}", -@"class C -{ - char M(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - return 'a'; - else - return 'a'; - } - - char N(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - return 'a'; - else - return 'a'; - } -}"); + """ + class C + { + char M(bool b, out int i, out int j) + { + if (b) + {|CS0177:{|CS0177:return 'a';|}|} + else + {|CS0177:{|CS0177:return 'a';|}|} + } + char N(bool b, out int i, out int j) + { + if (b) + {|CS0177:{|CS0177:return 'a';|}|} + else + {|CS0177:{|CS0177:return 'a';|}|} + } + } + """, + """ + class C + { + char M(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + return 'a'; + else + return 'a'; + } + + char N(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + return 'a'; + else + return 'a'; + } + } + """); } [Fact] public async Task TestFixAll3() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i, out int j) - { - if (b) - { - i = 0; - {|CS0177:return 'a';|} - } - else - { - j = 0; - {|CS0177:return 'a';|} - } - } -}", -@"class C -{ - char M(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - { - i = 0; - return 'a'; - } - else - { - j = 0; - return 'a'; - } - } -}"); + """ + class C + { + char M(bool b, out int i, out int j) + { + if (b) + { + i = 0; + {|CS0177:return 'a';|} + } + else + { + j = 0; + {|CS0177:return 'a';|} + } + } + } + """, + """ + class C + { + char M(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + { + i = 0; + return 'a'; + } + else + { + j = 0; + return 'a'; + } + } + } + """); } [Fact] public async Task TestFixAll3_MultipleMethods() { await VerifyCS.VerifyCodeFixAsync( -@"class C -{ - char M(bool b, out int i, out int j) - { - if (b) - { - i = 0; - {|CS0177:return 'a';|} - } - else - { - j = 0; - {|CS0177:return 'a';|} - } - } - char N(bool b, out int i, out int j) - { - if (b) - { - i = 0; - {|CS0177:return 'a';|} - } - else - { - j = 0; - {|CS0177:return 'a';|} - } - } -}", -@"class C -{ - char M(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - { - i = 0; - return 'a'; - } - else - { - j = 0; - return 'a'; - } - } - - char N(bool b, out int i, out int j) - { - i = 0; - j = 0; - if (b) - { - i = 0; - return 'a'; - } - else - { - j = 0; - return 'a'; - } - } -}"); + """ + class C + { + char M(bool b, out int i, out int j) + { + if (b) + { + i = 0; + {|CS0177:return 'a';|} + } + else + { + j = 0; + {|CS0177:return 'a';|} + } + } + char N(bool b, out int i, out int j) + { + if (b) + { + i = 0; + {|CS0177:return 'a';|} + } + else + { + j = 0; + {|CS0177:return 'a';|} + } + } + } + """, + """ + class C + { + char M(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + { + i = 0; + return 'a'; + } + else + { + j = 0; + return 'a'; + } + } + + char N(bool b, out int i, out int j) + { + i = 0; + j = 0; + if (b) + { + i = 0; + return 'a'; + } + else + { + j = 0; + return 'a'; + } + } + } + """); } } } diff --git a/src/Analyzers/CSharp/Tests/ConvertTypeOfToNameOf/ConvertTypeOfToNameOfFixAllTests.cs b/src/Analyzers/CSharp/Tests/ConvertTypeOfToNameOf/ConvertTypeOfToNameOfFixAllTests.cs index 9f7ef343e6e3e..a70f3112cef36 100644 --- a/src/Analyzers/CSharp/Tests/ConvertTypeOfToNameOf/ConvertTypeOfToNameOfFixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/ConvertTypeOfToNameOf/ConvertTypeOfToNameOfFixAllTests.cs @@ -20,27 +20,29 @@ public partial class ConvertTypeOfToNameOfTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task FixAllDocumentBasic() { - var input = @"class Test -{ - static void Main() - { - var typeName1 = [|typeof(Test).Name|]; - var typeName2 = [|typeof(Test).Name|]; - var typeName3 = [|typeof(Test).Name|]; - } -} -"; + var input = """ + class Test + { + static void Main() + { + var typeName1 = [|typeof(Test).Name|]; + var typeName2 = [|typeof(Test).Name|]; + var typeName3 = [|typeof(Test).Name|]; + } + } + """; - var expected = @"class Test -{ - static void Main() - { - var typeName1 = nameof(Test); - var typeName2 = nameof(Test); - var typeName3 = nameof(Test); - } -} -"; + var expected = """ + class Test + { + static void Main() + { + var typeName1 = nameof(Test); + var typeName2 = nameof(Test); + var typeName3 = nameof(Test); + } + } + """; await VerifyCS.VerifyCodeFixAsync(input, expected); } @@ -50,23 +52,25 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task FixAllDocumentVariedSingleLine() { - var input = @"class Test -{ - static void Main() - { - var typeName1 = [|typeof(Test).Name|]; var typeName2 = [|typeof(int).Name|]; var typeName3 = [|typeof(System.String).Name|]; - } -} -"; + var input = """ + class Test + { + static void Main() + { + var typeName1 = [|typeof(Test).Name|]; var typeName2 = [|typeof(int).Name|]; var typeName3 = [|typeof(System.String).Name|]; + } + } + """; - var expected = @"class Test -{ - static void Main() - { - var typeName1 = nameof(Test); var typeName2 = nameof(System.Int32); var typeName3 = nameof(System.String); - } -} -"; + var expected = """ + class Test + { + static void Main() + { + var typeName1 = nameof(Test); var typeName2 = nameof(System.Int32); var typeName3 = nameof(System.String); + } + } + """; await VerifyCS.VerifyCodeFixAsync(input, expected); } @@ -76,33 +80,35 @@ static void Main() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task FixAllDocumentVariedWithUsing() { - var input = @"using System; + var input = """ + using System; -class Test -{ - static void Main() - { - var typeName1 = [|typeof(Test).Name|]; - var typeName2 = [|typeof(int).Name|]; - var typeName3 = [|typeof(String).Name|]; - var typeName4 = [|typeof(System.Double).Name|]; - } -} -"; + class Test + { + static void Main() + { + var typeName1 = [|typeof(Test).Name|]; + var typeName2 = [|typeof(int).Name|]; + var typeName3 = [|typeof(String).Name|]; + var typeName4 = [|typeof(System.Double).Name|]; + } + } + """; - var expected = @"using System; + var expected = """ + using System; -class Test -{ - static void Main() - { - var typeName1 = nameof(Test); - var typeName2 = nameof(Int32); - var typeName3 = nameof(String); - var typeName4 = nameof(Double); - } -} -"; + class Test + { + static void Main() + { + var typeName1 = nameof(Test); + var typeName2 = nameof(Int32); + var typeName3 = nameof(String); + var typeName4 = nameof(Double); + } + } + """; await VerifyCS.VerifyCodeFixAsync(input, expected); } @@ -118,62 +124,62 @@ public async Task FixAllProject() { Sources = { - @" -class Test1 -{ - static void Main() - { - var typeName1 = [|typeof(Test1).Name|]; - var typeName2 = [|typeof(Test1).Name|]; - var typeName3 = [|typeof(Test1).Name|]; - } -} -", - @" -using System; + """ + class Test1 + { + static void Main() + { + var typeName1 = [|typeof(Test1).Name|]; + var typeName2 = [|typeof(Test1).Name|]; + var typeName3 = [|typeof(Test1).Name|]; + } + } + """, + """ + using System; -class Test2 -{ - static void Main() - { - var typeName1 = [|typeof(Test1).Name|]; - var typeName2 = [|typeof(int).Name|]; - var typeName3 = [|typeof(System.String).Name|]; - var typeName4 = [|typeof(Double).Name|]; - } -} -" + class Test2 + { + static void Main() + { + var typeName1 = [|typeof(Test1).Name|]; + var typeName2 = [|typeof(int).Name|]; + var typeName3 = [|typeof(System.String).Name|]; + var typeName4 = [|typeof(Double).Name|]; + } + } + """ } }, FixedState = { Sources = { - @" -class Test1 -{ - static void Main() - { - var typeName1 = nameof(Test1); - var typeName2 = nameof(Test1); - var typeName3 = nameof(Test1); - } -} -", - @" -using System; + """ + class Test1 + { + static void Main() + { + var typeName1 = nameof(Test1); + var typeName2 = nameof(Test1); + var typeName3 = nameof(Test1); + } + } + """, + """ + using System; -class Test2 -{ - static void Main() - { - var typeName1 = nameof(Test1); - var typeName2 = nameof(Int32); - var typeName3 = nameof(String); - var typeName4 = nameof(Double); - } -} -", + class Test2 + { + static void Main() + { + var typeName1 = nameof(Test1); + var typeName2 = nameof(Int32); + var typeName3 = nameof(String); + var typeName4 = nameof(Double); + } + } + """, } } }.RunAsync(); @@ -190,31 +196,31 @@ public async Task FixAllSolution() { Sources = { - @" -class Test1 -{ - static void Main() - { - var typeName1 = [|typeof(Test1).Name|]; - var typeName2 = [|typeof(Test1).Name|]; - var typeName3 = [|typeof(Test1).Name|]; - } -} -", - @" -using System; + """ + class Test1 + { + static void Main() + { + var typeName1 = [|typeof(Test1).Name|]; + var typeName2 = [|typeof(Test1).Name|]; + var typeName3 = [|typeof(Test1).Name|]; + } + } + """, + """ + using System; -class Test2 -{ - static void Main() - { - var typeName1 = [|typeof(Test1).Name|]; - var typeName2 = [|typeof(int).Name|]; - var typeName3 = [|typeof(System.String).Name|]; - var typeName4 = [|typeof(Double).Name|]; - } -} -" + class Test2 + { + static void Main() + { + var typeName1 = [|typeof(Test1).Name|]; + var typeName2 = [|typeof(int).Name|]; + var typeName3 = [|typeof(System.String).Name|]; + var typeName4 = [|typeof(Double).Name|]; + } + } + """ }, AdditionalProjects = { @@ -222,15 +228,15 @@ static void Main() { Sources = { - @" -class Test3 -{ - static void Main() - { - var typeName2 = [|typeof(int).Name|]; var typeName3 = [|typeof(System.String).Name|]; - } -} -" + """ + class Test3 + { + static void Main() + { + var typeName2 = [|typeof(int).Name|]; var typeName3 = [|typeof(System.String).Name|]; + } + } + """ } } } @@ -239,31 +245,31 @@ static void Main() { Sources = { - @" -class Test1 -{ - static void Main() - { - var typeName1 = nameof(Test1); - var typeName2 = nameof(Test1); - var typeName3 = nameof(Test1); - } -} -", - @" -using System; + """ + class Test1 + { + static void Main() + { + var typeName1 = nameof(Test1); + var typeName2 = nameof(Test1); + var typeName3 = nameof(Test1); + } + } + """, + """ + using System; -class Test2 -{ - static void Main() - { - var typeName1 = nameof(Test1); - var typeName2 = nameof(Int32); - var typeName3 = nameof(String); - var typeName4 = nameof(Double); - } -} -" + class Test2 + { + static void Main() + { + var typeName1 = nameof(Test1); + var typeName2 = nameof(Int32); + var typeName3 = nameof(String); + var typeName4 = nameof(Double); + } + } + """ }, AdditionalProjects = { @@ -271,15 +277,15 @@ static void Main() { Sources = { - @" -class Test3 -{ - static void Main() - { - var typeName2 = nameof(System.Int32); var typeName3 = nameof(System.String); - } -} -" + """ + class Test3 + { + static void Main() + { + var typeName2 = nameof(System.Int32); var typeName3 = nameof(System.String); + } + } + """ } } } diff --git a/src/Analyzers/CSharp/Tests/DocumentationComments/AddDocCommentNodesCodeFixProviderTests.cs b/src/Analyzers/CSharp/Tests/DocumentationComments/AddDocCommentNodesCodeFixProviderTests.cs index 86e46076581cf..3ec80a9afe51d 100644 --- a/src/Analyzers/CSharp/Tests/DocumentationComments/AddDocCommentNodesCodeFixProviderTests.cs +++ b/src/Analyzers/CSharp/Tests/DocumentationComments/AddDocCommentNodesCodeFixProviderTests.cs @@ -850,46 +850,46 @@ record R(int First, int Second, int Third); [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)] public async Task AddsParamTag_Class() { - var initial = @" -/// -/// -/// -/// -class R(int [|First|], int Second, int Third); -"; - - var expected = @" -/// -/// -/// -/// -/// -/// -class R(int First, int Second, int Third); -"; + var initial = """ + /// + /// + /// + /// + class R(int [|First|], int Second, int Third); + """; + + var expected = """ + /// + /// + /// + /// + /// + /// + class R(int First, int Second, int Third); + """; await TestAsync(initial, expected); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)] public async Task AddsParamTag_Struct() { - var initial = @" -/// -/// -/// -/// -struct R(int [|First|], int Second, int Third); -"; - - var expected = @" -/// -/// -/// -/// -/// -/// -struct R(int First, int Second, int Third); -"; + var initial = """ + /// + /// + /// + /// + struct R(int [|First|], int Second, int Third); + """; + + var expected = """ + /// + /// + /// + /// + /// + /// + struct R(int First, int Second, int Third); + """; await TestAsync(initial, expected); } } diff --git a/src/Analyzers/CSharp/Tests/ForEachCast/ForEachCastTests.cs b/src/Analyzers/CSharp/Tests/ForEachCast/ForEachCastTests.cs index d194b41165d70..e12d40ba42f01 100644 --- a/src/Analyzers/CSharp/Tests/ForEachCast/ForEachCastTests.cs +++ b/src/Analyzers/CSharp/Tests/ForEachCast/ForEachCastTests.cs @@ -1083,19 +1083,19 @@ public static void M((object, object)[] x) [Fact, WorkItem(63470, "https://github.com/dotnet/roslyn/issues/63470")] public async Task TestRegex_GoodCast() { - var test = @" -using System.Text.RegularExpressions; + var test = """ + using System.Text.RegularExpressions; -public static class Program -{ - public static void M(Regex regex, string text) - { - foreach (Match m in regex.Matches(text)) - { - } - } -} -"; + public static class Program + { + public static void M(Regex regex, string text) + { + foreach (Match m in regex.Matches(text)) + { + } + } + } + """; await TestAlwaysAsync(test, test, ReferenceAssemblies.Net.Net80); await TestWhenStronglyTypedAsync(test, test, ReferenceAssemblies.Net.Net80); } @@ -1103,33 +1103,33 @@ public static void M(Regex regex, string text) [Fact, WorkItem(63470, "https://github.com/dotnet/roslyn/issues/63470")] public async Task TestRegex_BadCast() { - var test = @" -using System.Text.RegularExpressions; + var test = """ + using System.Text.RegularExpressions; -public static class Program -{ - public static void M(Regex regex, string text) - { - [|foreach|] (string m in regex.Matches(text)) - { - } - } -} -"; - var code = @" -using System.Linq; -using System.Text.RegularExpressions; - -public static class Program -{ - public static void M(Regex regex, string text) - { - foreach (string m in regex.Matches(text).Cast()) - { - } - } -} -"; + public static class Program + { + public static void M(Regex regex, string text) + { + [|foreach|] (string m in regex.Matches(text)) + { + } + } + } + """; + var code = """ + using System.Linq; + using System.Text.RegularExpressions; + + public static class Program + { + public static void M(Regex regex, string text) + { + foreach (string m in regex.Matches(text).Cast()) + { + } + } + } + """; await TestAlwaysAsync(test, code, ReferenceAssemblies.Net.Net80); await TestWhenStronglyTypedAsync(test, code, ReferenceAssemblies.Net.Net80); } @@ -1137,44 +1137,44 @@ public static void M(Regex regex, string text) [Fact, WorkItem(63470, "https://github.com/dotnet/roslyn/issues/63470")] public async Task WeaklyTypedGetEnumeratorWithIEnumerableOfT() { - var test = @" -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text.RegularExpressions; + var test = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Text.RegularExpressions; -public class C : IEnumerable -{ - public IEnumerator GetEnumerator() => new Enumerator(); // compiler picks this for the foreach loop. + public class C : IEnumerable + { + public IEnumerator GetEnumerator() => new Enumerator(); // compiler picks this for the foreach loop. - IEnumerator IEnumerable.GetEnumerator() => null; // compiler doesn't use this. + IEnumerator IEnumerable.GetEnumerator() => null; // compiler doesn't use this. - public static void M(C c) - { - // The compiler adds a cast here from 'object' to 'Match', - // and it will fail at runtime because GetEnumerator().Current will return a string. - // This is due to badly implemented type 'C', and is rare enough. So, we don't report here - // to reduce false positives. - foreach (Match x in c) - { - } - } + public static void M(C c) + { + // The compiler adds a cast here from 'object' to 'Match', + // and it will fail at runtime because GetEnumerator().Current will return a string. + // This is due to badly implemented type 'C', and is rare enough. So, we don't report here + // to reduce false positives. + foreach (Match x in c) + { + } + } - private class Enumerator : IEnumerator - { - public object Current => ""String""; + private class Enumerator : IEnumerator + { + public object Current => "String"; - public bool MoveNext() - { - return true; - } + public bool MoveNext() + { + return true; + } - public void Reset() - { - } - } -} -"; + public void Reset() + { + } + } + } + """; await TestAlwaysAsync(test, test); await TestWhenStronglyTypedAsync(test, test); } @@ -1182,74 +1182,74 @@ public void Reset() [Fact, WorkItem(63470, "https://github.com/dotnet/roslyn/issues/63470")] public async Task WeaklyTypedGetEnumeratorWithIEnumerableOfT_DifferentTypeUsedInForEach() { - var code = @" -using System; -using System.Collections; -using System.Collections.Generic; + var code = """ + using System; + using System.Collections; + using System.Collections.Generic; -public class C : IEnumerable -{ - public IEnumerator GetEnumerator() => new Enumerator(); // compiler picks this for the foreach loop. + public class C : IEnumerable + { + public IEnumerator GetEnumerator() => new Enumerator(); // compiler picks this for the foreach loop. - IEnumerator IEnumerable.GetEnumerator() => null; // compiler doesn't use this. + IEnumerator IEnumerable.GetEnumerator() => null; // compiler doesn't use this. - public static void M(C c) - { - [|foreach|] (C x in c) - { - } - } + public static void M(C c) + { + [|foreach|] (C x in c) + { + } + } - private class Enumerator : IEnumerator - { - public object Current => ""String""; + private class Enumerator : IEnumerator + { + public object Current => "String"; - public bool MoveNext() - { - return true; - } + public bool MoveNext() + { + return true; + } - public void Reset() - { - } - } -} -"; + public void Reset() + { + } + } + } + """; - var fixedCode = @" -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; + var fixedCode = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; -public class C : IEnumerable -{ - public IEnumerator GetEnumerator() => new Enumerator(); // compiler picks this for the foreach loop. + public class C : IEnumerable + { + public IEnumerator GetEnumerator() => new Enumerator(); // compiler picks this for the foreach loop. - IEnumerator IEnumerable.GetEnumerator() => null; // compiler doesn't use this. + IEnumerator IEnumerable.GetEnumerator() => null; // compiler doesn't use this. - public static void M(C c) - { - foreach (C x in c.Cast()) - { - } - } + public static void M(C c) + { + foreach (C x in c.Cast()) + { + } + } - private class Enumerator : IEnumerator - { - public object Current => ""String""; + private class Enumerator : IEnumerator + { + public object Current => "String"; - public bool MoveNext() - { - return true; - } + public bool MoveNext() + { + return true; + } - public void Reset() - { - } - } -} -"; + public void Reset() + { + } + } + } + """; await TestAlwaysAsync(code, fixedCode); await TestWhenStronglyTypedAsync(code, fixedCode); } @@ -1259,58 +1259,58 @@ public async Task WeaklyTypedGetEnumeratorWithMultipleIEnumerableOfT() { // NOTE: The analyzer only considers the first IEnumerable implementation. // That is why the following tests produces a diagnostic for the implicit string cast, but not for the implicit int cast. - var test = @" -using System; -using System.Collections; -using System.Collections.Generic; + var test = """ + using System; + using System.Collections; + using System.Collections.Generic; -public class C : IEnumerable, IEnumerable -{ - public IEnumerator GetEnumerator() => null; + public class C : IEnumerable, IEnumerable + { + public IEnumerator GetEnumerator() => null; - IEnumerator IEnumerable.GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; - IEnumerator IEnumerable.GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; - public static void M(C c) - { - foreach (int x in c) - { - } + public static void M(C c) + { + foreach (int x in c) + { + } - [|foreach|] (string x in c) - { - } - } -} -"; + [|foreach|] (string x in c) + { + } + } + } + """; - var fixedCode = @" -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; + var fixedCode = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; -public class C : IEnumerable, IEnumerable -{ - public IEnumerator GetEnumerator() => null; + public class C : IEnumerable, IEnumerable + { + public IEnumerator GetEnumerator() => null; - IEnumerator IEnumerable.GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; - IEnumerator IEnumerable.GetEnumerator() => null; + IEnumerator IEnumerable.GetEnumerator() => null; - public static void M(C c) - { - foreach (int x in c) - { - } + public static void M(C c) + { + foreach (int x in c) + { + } - foreach (string x in c.Cast()) - { - } - } -} -"; + foreach (string x in c.Cast()) + { + } + } + } + """; await TestAlwaysAsync(test, fixedCode); await TestWhenStronglyTypedAsync(test, fixedCode); } diff --git a/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs b/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs index e224b25ada85e..cc87cca3f27d4 100644 --- a/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs +++ b/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests.cs @@ -2369,39 +2369,41 @@ static void M(bool condition) public async Task TestDefiniteAssignment3(string input, string output) { await TestInRegularAndScript1Async( -$@" -using System; - -class C -{{ - static bool M(out bool i) => throw null; - static bool Use(bool i) => throw null; - - static void M(bool c) - {{ - [|bool|] x = false; - if ({input}) - {{ - Console.WriteLine(x); - }} - }} -}}", -$@" -using System; - -class C -{{ - static bool M(out bool i) => throw null; - static bool Use(bool i) => throw null; - - static void M(bool c) - {{ - if ({output}) - {{ - Console.WriteLine(x); - }} - }} -}}"); + $$""" + using System; + + class C + { + static bool M(out bool i) => throw null; + static bool Use(bool i) => throw null; + + static void M(bool c) + { + [|bool|] x = false; + if ({{input}}) + { + Console.WriteLine(x); + } + } + } + """, + $$""" + using System; + + class C + { + static bool M(out bool i) => throw null; + static bool Use(bool i) => throw null; + + static void M(bool c) + { + if ({{output}}) + { + Console.WriteLine(x); + } + } + } + """); } [Fact] diff --git a/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests_FixAllTests.cs index ec9d1c5e5ebda..5e1796a134906 100644 --- a/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/InlineDeclaration/CSharpInlineDeclarationTests_FixAllTests.cs @@ -18,25 +18,29 @@ public partial class CSharpInlineDeclarationTests public async Task FixAllInDocument1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i|}, j; - if (int.TryParse(v, out i, out j)) - { - } - } -}", -@"class C -{ - void M() - { - if (int.TryParse(v, out int i, out int j)) - { - } - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i|}, j; + if (int.TryParse(v, out i, out j)) + { + } + } + } + """, + """ + class C + { + void M() + { + if (int.TryParse(v, out int i, out int j)) + { + } + } + } + """); } [Fact] @@ -44,386 +48,442 @@ public async Task FixAllInDocument2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - {|FixAllInDocument:int|} i; - if (int.TryParse(v, out i)) - { - } - } + """ + class C + { + void M() + { + {|FixAllInDocument:int|} i; + if (int.TryParse(v, out i)) + { + } + } - void M1() - { - int i; - if (int.TryParse(v, out i)) - { - } - } -}", -@"class C -{ - void M() - { - if (int.TryParse(v, out int i)) - { - } - } + void M1() + { + int i; + if (int.TryParse(v, out i)) + { + } + } + } + """, + """ + class C + { + void M() + { + if (int.TryParse(v, out int i)) + { + } + } - void M1() - { - if (int.TryParse(v, out int i)) - { - } - } -}"); + void M1() + { + if (int.TryParse(v, out int i)) + { + } + } + } + """); } [Fact] public async Task FixAllInDocument3() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - // Now get final exe and args. CTtrl-F5 wraps exe in cmd prompt - string {|FixAllInDocument:finalExecutable|}, finalArguments; - GetExeAndArguments(useCmdShell, executable, arguments, out finalExecutable, out finalArguments); - } -}", -@"class C -{ - void M() - { - // Now get final exe and args. CTtrl-F5 wraps exe in cmd prompt - GetExeAndArguments(useCmdShell, executable, arguments, out string finalExecutable, out string finalArguments); - } -}"); + """ + class C + { + void M() + { + // Now get final exe and args. CTtrl-F5 wraps exe in cmd prompt + string {|FixAllInDocument:finalExecutable|}, finalArguments; + GetExeAndArguments(useCmdShell, executable, arguments, out finalExecutable, out finalArguments); + } + } + """, + """ + class C + { + void M() + { + // Now get final exe and args. CTtrl-F5 wraps exe in cmd prompt + GetExeAndArguments(useCmdShell, executable, arguments, out string finalExecutable, out string finalArguments); + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/29935")] public async Task FixAllInDocumentSymbolResolution() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - string {|FixAllInDocument:s|}; - bool b; - A(out s, out b); - } + """ + class C + { + void M() + { + string {|FixAllInDocument:s|}; + bool b; + A(out s, out b); + } - void A(out string s, out bool b) - { - s = string.Empty; - b = false; - } + void A(out string s, out bool b) + { + s = string.Empty; + b = false; + } - void A(out string s, out string s2) - { - s = s2 = string.Empty; - } -}", -@"class C -{ - void M() - { - A(out string s, out bool b); - } + void A(out string s, out string s2) + { + s = s2 = string.Empty; + } + } + """, + """ + class C + { + void M() + { + A(out string s, out bool b); + } - void A(out string s, out bool b) - { - s = string.Empty; - b = false; - } + void A(out string s, out bool b) + { + s = string.Empty; + b = false; + } - void A(out string s, out string s2) - { - s = s2 = string.Empty; - } -}"); + void A(out string s, out string s2) + { + s = s2 = string.Empty; + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocument4() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}; int i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - } -}", -@"class C -{ - void M() - { - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}; int i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + } + } + """, + """ + class C + { + void M() + { + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocument5() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int dummy; int {|FixAllInDocument:i1|}; int i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - int dummy; - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int dummy; int {|FixAllInDocument:i1|}; int i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + int dummy; + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocument6() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}; int dummy; int i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - int dummy; - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}; int dummy; int i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + int dummy; + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocument7() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}; int i2; int dummy; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - int dummy; - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}; int i2; int dummy; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + int dummy; + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact] public async Task FixAllInDocument8() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int dummy, {|FixAllInDocument:i1|}, i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - int dummy; - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int dummy, {|FixAllInDocument:i1|}, i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + int dummy; + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact] public async Task FixAllInDocument9() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}, dummy, i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - int dummy; - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}, dummy, i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + int dummy; + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact] public async Task FixAllInDocument10() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}, i2, dummy; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - int dummy; - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}, i2, dummy; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + int dummy; + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact] public async Task FixAllInDocument11() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}, i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - } -}", -@"class C -{ - void M() - { - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}, i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + } + } + """, + """ + class C + { + void M() + { + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocumentComments1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - /* leading */ int {|FixAllInDocument:i1|}; int i2; // trailing - int.TryParse(v, out i1); - int.TryParse(v, out i2); - } -}", -@"class C -{ - void M() - { - /* leading */ // trailing - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - } -}"); + """ + class C + { + void M() + { + /* leading */ int {|FixAllInDocument:i1|}; int i2; // trailing + int.TryParse(v, out i1); + int.TryParse(v, out i2); + } + } + """, + """ + class C + { + void M() + { + /* leading */ // trailing + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocumentComments2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - /* leading */ int dummy; /* in-between */ int {|FixAllInDocument:i1|}; int i2; // trailing - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - /* leading */ int dummy; /* in-between */ // trailing - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + /* leading */ int dummy; /* in-between */ int {|FixAllInDocument:i1|}; int i2; // trailing + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + /* leading */ int dummy; /* in-between */ // trailing + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28323")] public async Task FixAllInDocumentComments3() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int {|FixAllInDocument:i1|}; /* 0 */int /* 1 */ dummy /* 2 */; /* 3*/ int i2; - int.TryParse(v, out i1); - int.TryParse(v, out i2); - dummy = 42; - } -}", -@"class C -{ - void M() - { - /* 0 */ - int /* 1 */ dummy /* 2 */; /* 3*/ - int.TryParse(v, out int i1); - int.TryParse(v, out int i2); - dummy = 42; - } -}"); + """ + class C + { + void M() + { + int {|FixAllInDocument:i1|}; /* 0 */int /* 1 */ dummy /* 2 */; /* 3*/ int i2; + int.TryParse(v, out i1); + int.TryParse(v, out i2); + dummy = 42; + } + } + """, + """ + class C + { + void M() + { + /* 0 */ + int /* 1 */ dummy /* 2 */; /* 3*/ + int.TryParse(v, out int i1); + int.TryParse(v, out int i2); + dummy = 42; + } + } + """); } } } diff --git a/src/Analyzers/CSharp/Tests/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessTests_FixAllTests.cs index 5079cc29cec89..5ccf06df80da4 100644 --- a/src/Analyzers/CSharp/Tests/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessTests_FixAllTests.cs @@ -17,216 +17,240 @@ public partial class InvokeDelegateWithConditionalAccessTests public async Task TestFixAllInDocument1() { await TestInRegularAndScriptAsync( -@"class C -{ - System.Action a; - - void Goo() - { - {|FixAllInDocument:var|} v = a; - if (v != null) - { - v(); - } - - var x = a; - if (x != null) - { - x(); - } - } -}", -@"class C -{ - System.Action a; - - void Goo() - { - a?.Invoke(); - - a?.Invoke(); - } -}"); + """ + class C + { + System.Action a; + + void Goo() + { + {|FixAllInDocument:var|} v = a; + if (v != null) + { + v(); + } + + var x = a; + if (x != null) + { + x(); + } + } + } + """, + """ + class C + { + System.Action a; + + void Goo() + { + a?.Invoke(); + + a?.Invoke(); + } + } + """); } [Fact] public async Task TestFixAllInDocument2() { await TestInRegularAndScriptAsync( -@"class C -{ - System.Action a; - - void Goo() - { - var v = a; - {|FixAllInDocument:if|} (v != null) - { - v(); - } - - var x = a; - if (x != null) - { - x(); - } - } -}", -@"class C -{ - System.Action a; - - void Goo() - { - a?.Invoke(); - - a?.Invoke(); - } -}"); + """ + class C + { + System.Action a; + + void Goo() + { + var v = a; + {|FixAllInDocument:if|} (v != null) + { + v(); + } + + var x = a; + if (x != null) + { + x(); + } + } + } + """, + """ + class C + { + System.Action a; + + void Goo() + { + a?.Invoke(); + + a?.Invoke(); + } + } + """); } [Fact] public async Task TestFixAllInDocument3() { await TestInRegularAndScriptAsync( -@"class C -{ - System.Action a; - - void Goo() - { - var v = a; - if (v != null) - { - {|FixAllInDocument:v|}(); - } - - var x = a; - if (x != null) - { - x(); - } - } -}", -@"class C -{ - System.Action a; - - void Goo() - { - a?.Invoke(); - - a?.Invoke(); - } -}"); + """ + class C + { + System.Action a; + + void Goo() + { + var v = a; + if (v != null) + { + {|FixAllInDocument:v|}(); + } + + var x = a; + if (x != null) + { + x(); + } + } + } + """, + """ + class C + { + System.Action a; + + void Goo() + { + a?.Invoke(); + + a?.Invoke(); + } + } + """); } [Fact] public async Task TestFixAllInDocument4() { await TestInRegularAndScriptAsync( -@"class C -{ - System.Action a; - - void Goo() - { - var v = a; - if (v != null) - { - v(); - } - - {|FixAllInDocument:var|} x = a; - if (x != null) - { - x(); - } - } -}", -@"class C -{ - System.Action a; - - void Goo() - { - a?.Invoke(); - - a?.Invoke(); - } -}"); + """ + class C + { + System.Action a; + + void Goo() + { + var v = a; + if (v != null) + { + v(); + } + + {|FixAllInDocument:var|} x = a; + if (x != null) + { + x(); + } + } + } + """, + """ + class C + { + System.Action a; + + void Goo() + { + a?.Invoke(); + + a?.Invoke(); + } + } + """); } [Fact] public async Task TestFixAllInDocument5() { await TestInRegularAndScriptAsync( -@"class C -{ - System.Action a; - - void Goo() - { - var v = a; - if (v != null) - { - v(); - } - - var x = a; - {|FixAllInDocument:if|} (x != null) - { - x(); - } - } -}", -@"class C -{ - System.Action a; - - void Goo() - { - a?.Invoke(); - - a?.Invoke(); - } -}"); + """ + class C + { + System.Action a; + + void Goo() + { + var v = a; + if (v != null) + { + v(); + } + + var x = a; + {|FixAllInDocument:if|} (x != null) + { + x(); + } + } + } + """, + """ + class C + { + System.Action a; + + void Goo() + { + a?.Invoke(); + + a?.Invoke(); + } + } + """); } [Fact] public async Task TestFixAllInDocument6() { await TestInRegularAndScriptAsync( -@"class C -{ - System.Action a; - - void Goo() - { - var v = a; - if (v != null) - { - v(); - } - - var x = a; - if (x != null) - { - {|FixAllInDocument:x|}(); - } - } -}", -@"class C -{ - System.Action a; - - void Goo() - { - a?.Invoke(); - - a?.Invoke(); - } -}"); + """ + class C + { + System.Action a; + + void Goo() + { + var v = a; + if (v != null) + { + v(); + } + + var x = a; + if (x != null) + { + {|FixAllInDocument:x|}(); + } + } + } + """, + """ + class C + { + System.Action a; + + void Goo() + { + a?.Invoke(); + + a?.Invoke(); + } + } + """); } } } diff --git a/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs b/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs index ee046d1e9a6c7..3a6d90d4f4e8a 100644 --- a/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.MakeFieldReadonly [Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)] public class MakeFieldReadonlyTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor { - private static readonly ParseOptions s_strictFeatureFlag = CSharpParseOptions.Default.WithFeatures(new[] { new KeyValuePair("strict", "true") }); + private static readonly ParseOptions s_strictFeatureFlag = CSharpParseOptions.Default.WithFeatures([new KeyValuePair("strict", "true")]); public MakeFieldReadonlyTests(ITestOutputHelper logger) : base(logger) diff --git a/src/Analyzers/CSharp/Tests/MakeMemberRequired/MakeMemberRequiredTests.cs b/src/Analyzers/CSharp/Tests/MakeMemberRequired/MakeMemberRequiredTests.cs index 2dfb732c425ca..abdccdebc290b 100644 --- a/src/Analyzers/CSharp/Tests/MakeMemberRequired/MakeMemberRequiredTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeMemberRequired/MakeMemberRequiredTests.cs @@ -120,8 +120,7 @@ public static IEnumerable AccessorAccessibilityModifierCombinationsWhe yield return new[] { "internal", "private protected" }; } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68478")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68478")] public async Task SimpleSetPropertyMissingRequiredAttribute() { var code = diff --git a/src/Analyzers/CSharp/Tests/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs b/src/Analyzers/CSharp/Tests/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs index a639e6353e250..c00f0094868f2 100644 --- a/src/Analyzers/CSharp/Tests/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs @@ -1229,42 +1229,46 @@ async Task M3Async() public async Task AddAsyncInLocalFunctionKeepsTrivia(int codeFixIndex, string initialReturn, string expectedReturn, string expectedName) { await TestInRegularAndScriptAsync( -$@"using System.Threading.Tasks; - -class C -{{ - public void M1() - {{ - // Leading trivia - /*1*/ {initialReturn} /*2*/ M2/*3*/() /*4*/ - {{ - [|await M3Async();|] - }} - }} - - async Task M3Async() - {{ - return 1; - }} -}}", -$@"using System.Threading.Tasks; - -class C -{{ - public void M1() - {{ - // Leading trivia - /*1*/ async {expectedReturn} /*2*/ {expectedName}/*3*/() /*4*/ - {{ - await M3Async(); - }} - }} - - async Task M3Async() - {{ - return 1; - }} -}}", + $$""" + using System.Threading.Tasks; + + class C + { + public void M1() + { + // Leading trivia + /*1*/ {{initialReturn}} /*2*/ M2/*3*/() /*4*/ + { + [|await M3Async();|] + } + } + + async Task M3Async() + { + return 1; + } + } + """, + $$""" + using System.Threading.Tasks; + + class C + { + public void M1() + { + // Leading trivia + /*1*/ async {{expectedReturn}} /*2*/ {{expectedName}}/*3*/() /*4*/ + { + await M3Async(); + } + } + + async Task M3Async() + { + return 1; + } + } + """, index: codeFixIndex); } @@ -1278,36 +1282,40 @@ async Task M3Async() public async Task AddAsyncKeepsTrivia(string modifiers, int codeFixIndex, string expectedReturn, string expectedName) { await TestInRegularAndScriptAsync( -$@"using System.Threading.Tasks; - -class C -{{ - // Leading trivia - {modifiers}/*1*/ void /*2*/ M2/*3*/() /*4*/ - {{ - [|await M3Async();|] - }} - - async Task M3Async() - {{ - return 1; - }} -}}", -$@"using System.Threading.Tasks; - -class C -{{ - // Leading trivia - {modifiers}/*1*/ async {expectedReturn} /*2*/ {expectedName}/*3*/() /*4*/ - {{ - await M3Async(); - }} - - async Task M3Async() - {{ - return 1; - }} -}}", + $$""" + using System.Threading.Tasks; + + class C + { + // Leading trivia + {{modifiers}}/*1*/ void /*2*/ M2/*3*/() /*4*/ + { + [|await M3Async();|] + } + + async Task M3Async() + { + return 1; + } + } + """, + $$""" + using System.Threading.Tasks; + + class C + { + // Leading trivia + {{modifiers}}/*1*/ async {{expectedReturn}} /*2*/ {{expectedName}}/*3*/() /*4*/ + { + await M3Async(); + } + + async Task M3Async() + { + return 1; + } + } + """, index: codeFixIndex); } diff --git a/src/Analyzers/CSharp/Tests/MakeMethodSynchronous/MakeMethodSynchronousTests.cs b/src/Analyzers/CSharp/Tests/MakeMethodSynchronous/MakeMethodSynchronousTests.cs index 451020ace1fc8..5b8e275be6ed9 100644 --- a/src/Analyzers/CSharp/Tests/MakeMethodSynchronous/MakeMethodSynchronousTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeMethodSynchronous/MakeMethodSynchronousTests.cs @@ -784,35 +784,39 @@ void M2() public async Task RemoveAsyncInLocalFunctionKeepsTrivia(string asyncReturn, string expectedReturn) { await VerifyCS.VerifyCodeFixAsync( -$@"using System; -using System.Threading.Tasks; + $$""" + using System; + using System.Threading.Tasks; -class C -{{ - public void M1() - {{ - // Leading trivia - /*1*/ async {asyncReturn} /*2*/ {{|CS1998:M2Async|}}/*3*/() /*4*/ - {{ - throw new NotImplementedException(); - }} - }} -}}", -$@"using System; -using System.Threading.Tasks; + class C + { + public void M1() + { + // Leading trivia + /*1*/ async {{asyncReturn}} /*2*/ {|CS1998:M2Async|}/*3*/() /*4*/ + { + throw new NotImplementedException(); + } + } + } + """, + $$""" + using System; + using System.Threading.Tasks; -class C -{{ - public void M1() - {{ - // Leading trivia - /*1*/ - {expectedReturn} /*2*/ M2/*3*/() /*4*/ - {{ - throw new NotImplementedException(); - }} - }} -}}"); + class C + { + public void M1() + { + // Leading trivia + /*1*/ + {{expectedReturn}} /*2*/ M2/*3*/() /*4*/ + { + throw new NotImplementedException(); + } + } + } + """); } [Theory] @@ -829,28 +833,32 @@ public void M1() public async Task RemoveAsyncKeepsTrivia(string modifiers, string asyncReturn, string expectedReturn) { await VerifyCS.VerifyCodeFixAsync( -$@"using System; -using System.Threading.Tasks; + $$""" + using System; + using System.Threading.Tasks; -class C -{{ - // Leading trivia - {modifiers}/*1*/ async {asyncReturn} /*2*/ {{|CS1998:M2Async|}}/*3*/() /*4*/ - {{ - throw new NotImplementedException(); - }} -}}", -$@"using System; -using System.Threading.Tasks; + class C + { + // Leading trivia + {{modifiers}}/*1*/ async {{asyncReturn}} /*2*/ {|CS1998:M2Async|}/*3*/() /*4*/ + { + throw new NotImplementedException(); + } + } + """, + $$""" + using System; + using System.Threading.Tasks; -class C -{{ - // Leading trivia - {modifiers}/*1*/{expectedReturn} /*2*/ M2/*3*/() /*4*/ - {{ - throw new NotImplementedException(); - }} -}}"); + class C + { + // Leading trivia + {{modifiers}}/*1*/{{expectedReturn}} /*2*/ M2/*3*/() /*4*/ + { + throw new NotImplementedException(); + } + } + """); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeMethodSynchronous)] diff --git a/src/Analyzers/CSharp/Tests/MakeStructReadOnly/MakeStructReadOnlyTests.cs b/src/Analyzers/CSharp/Tests/MakeStructReadOnly/MakeStructReadOnlyTests.cs index 36beded885982..182548e279f1b 100644 --- a/src/Analyzers/CSharp/Tests/MakeStructReadOnly/MakeStructReadOnlyTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeStructReadOnly/MakeStructReadOnlyTests.cs @@ -155,10 +155,12 @@ record struct S(int j) public async Task TestMissingWithMutableAndReadOnlyFieldStruct2() { await TestMissingAsync( -@"struct S(int j) -{ - int i; -}"); + """ + struct S(int j) + { + int i; + } + """); } [Fact] @@ -201,10 +203,12 @@ record struct S(int q) public async Task TestMissingWithMutablePropertyStruct2() { await TestMissingAsync( -@"struct S(int q) -{ - int P { get; set; } -}"); + """ + struct S(int q) + { + int P { get; set; } + } + """); } [Fact] @@ -244,9 +248,11 @@ record struct S() public async Task TestMissingWithEmptyStructPrimaryConstructor() { await TestMissingAsync( -@"struct S() -{ -}"); + """ + struct S() + { + } + """); } [Fact] @@ -406,9 +412,11 @@ record struct S(int i) public async Task TestMissingStructWithPrimaryConstructor() { await TestMissingAsync( -@"struct S(int i) -{ -}"); + """ + struct S(int i) + { + } + """); } [Fact] @@ -427,14 +435,18 @@ record struct S(int i) public async Task TestOnStructWithPrimaryConstructorAndReadonlyField() { await TestAsync( -@"struct [|S|](int i) -{ - readonly int i; -}", -@"readonly struct S(int i) -{ - readonly int i; -}", + """ + struct [|S|](int i) + { + readonly int i; + } + """, + """ + readonly struct S(int i) + { + readonly int i; + } + """, LanguageVersion.CSharp12); } diff --git a/src/Analyzers/CSharp/Tests/MisplacedUsingDirectives/MisplacedUsingDirectivesTests.cs b/src/Analyzers/CSharp/Tests/MisplacedUsingDirectives/MisplacedUsingDirectivesTests.cs index cf833ccadfcb6..e7c3ad44d4326 100644 --- a/src/Analyzers/CSharp/Tests/MisplacedUsingDirectives/MisplacedUsingDirectivesTests.cs +++ b/src/Analyzers/CSharp/Tests/MisplacedUsingDirectives/MisplacedUsingDirectivesTests.cs @@ -151,10 +151,11 @@ namespace TestNamespace [InlineData(DelegateDefinition)] public Task WhenPreserve_UsingsInCompilationUnitWithTypeDefinition_ValidUsingStatements(string typeDefinition) { - var testCode = $@"[|using System;|] + var testCode = $""" + [|using System;|] -{typeDefinition} -"; + {typeDefinition} + """; return TestDiagnosticMissingAsync(testCode, InsidePreferPreservationOption); } @@ -246,10 +247,11 @@ namespace TestNamespace; [InlineData(DelegateDefinition)] public Task WhenOutsidePreferred_UsingsInCompilationUnitWithMember_ValidUsingStatements(string typeDefinition) { - var testCode = $@"[|using System;|] + var testCode = $""" + [|using System;|] -{typeDefinition} -"; + {typeDefinition} + """; return TestDiagnosticMissingAsync(testCode, OutsideNamespaceOption); } @@ -757,10 +759,11 @@ namespace TestNamespace; [InlineData(DelegateDefinition)] public Task WhenInsidePreferred_UsingsInCompilationUnitWithTypeDefinition_ValidUsingStatements(string typeDefinition) { - var testCode = $@"[|using System;|] + var testCode = $""" + [|using System;|] -{typeDefinition} -"; + {typeDefinition} + """; return TestDiagnosticMissingAsync(testCode, InsideNamespaceOption); } diff --git a/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs b/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs index 0501f81395c2b..86ed09ff64280 100644 --- a/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs +++ b/src/Analyzers/CSharp/Tests/NamingStyles/NamingStylesTests.cs @@ -40,21 +40,27 @@ protected override TestComposition GetComposition() public async Task TestPascalCaseClass_CorrectName() { await TestMissingInRegularAndScriptAsync( -@"class [|C|] -{ -}", new TestParameters(options: s_options.ClassNamesArePascalCase)); + """ + class [|C|] + { + } + """, new TestParameters(options: s_options.ClassNamesArePascalCase)); } [Fact] public async Task TestPascalCaseClass_NameGetsCapitalized() { await TestInRegularAndScriptAsync( -@"class [|c|] -{ -}", -@"class C -{ -}", + """ + class [|c|] + { + } + """, + """ + class C + { + } + """, options: s_options.ClassNamesArePascalCase); } @@ -80,14 +86,18 @@ await TestInRegularAndScriptAsync( public async Task TestCamelCaseField_PrefixGetsStripped(string fieldName, string correctedName) { await TestInRegularAndScriptAsync( -$@"class C -{{ - int [|{fieldName}|]; -}}", -$@"class C -{{ - int [|{correctedName}|]; -}}", + $$""" + class C + { + int [|{{fieldName}}|]; + } + """, + $$""" + class C + { + int [|{{correctedName}}|]; + } + """, options: s_options.FieldNamesAreCamelCase); } @@ -114,14 +124,18 @@ await TestInRegularAndScriptAsync( public async Task TestCamelCaseField_PrefixGetsStrippedBeforeAddition(string fieldName, string correctedName) { await TestInRegularAndScriptAsync( -$@"class C -{{ - int [|{fieldName}|]; -}}", -$@"class C -{{ - int [|{correctedName}|]; -}}", + $$""" + class C + { + int [|{{fieldName}}|]; + } + """, + $$""" + class C + { + int [|{{correctedName}}|]; + } + """, options: s_options.FieldNamesAreCamelCaseWithUnderscorePrefix); } @@ -129,12 +143,14 @@ await TestInRegularAndScriptAsync( public async Task TestPascalCaseMethod_CorrectName() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void [|M|]() - { - } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + """ + class C + { + void [|M|]() + { + } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Theory] @@ -149,26 +165,32 @@ await TestMissingInRegularAndScriptAsync( public async Task TestPascalCaseMethod_NoneAndDefaultAccessibilities(string accessibility) { await TestMissingInRegularAndScriptAsync( -$@"class C -{{ - {accessibility} void [|m|]() - {{ - }} -}}", new TestParameters(options: s_options.MethodNamesWithAccessibilityArePascalCase([]))); + $$""" + class C + { + {{accessibility}} void [|m|]() + { + } + } + """, new TestParameters(options: s_options.MethodNamesWithAccessibilityArePascalCase([]))); await TestInRegularAndScriptAsync( -$@"class C -{{ - {accessibility} void [|m|]() - {{ - }} -}}", -$@"class C -{{ - {accessibility} void M() - {{ - }} -}}", options: s_options.MethodNamesWithAccessibilityArePascalCase(accessibilities: default)); + $$""" + class C + { + {{accessibility}} void [|m|]() + { + } + } + """, + $$""" + class C + { + {{accessibility}} void M() + { + } + } + """, options: s_options.MethodNamesWithAccessibilityArePascalCase(accessibilities: default)); } [Theory] @@ -191,20 +213,26 @@ await TestInRegularAndScriptAsync( public async Task TestPascalCaseSymbol_NoneAndDefaultSymbolKinds(string camelCaseSymbol, string pascalCaseSymbol) { await TestMissingInRegularAndScriptAsync( -$@"class C -{{ - {camelCaseSymbol} -}}", new TestParameters(options: s_options.SymbolKindsArePascalCaseEmpty())); + $$""" + class C + { + {{camelCaseSymbol}} + } + """, new TestParameters(options: s_options.SymbolKindsArePascalCaseEmpty())); await TestInRegularAndScriptAsync( -$@"class C -{{ - {camelCaseSymbol} -}}", -$@"class C -{{ - {pascalCaseSymbol} -}}", options: s_options.SymbolKindsArePascalCase(symbolKinds: default)); + $$""" + class C + { + {{camelCaseSymbol}} + } + """, + $$""" + class C + { + {{pascalCaseSymbol}} + } + """, options: s_options.SymbolKindsArePascalCase(symbolKinds: default)); } [Theory] @@ -236,45 +264,57 @@ public async Task TestPascalCaseSymbol_ExpectedSymbolAndAccessibility(string cam // Verify that no diagnostic is reported if the symbol kind is wrong await TestMissingInRegularAndScriptAsync( -$@"class C -{{ - {camelCaseSymbol} -}}", new TestParameters(options: s_options.SymbolKindsArePascalCase(alternateSymbolKind))); + $$""" + class C + { + {{camelCaseSymbol}} + } + """, new TestParameters(options: s_options.SymbolKindsArePascalCase(alternateSymbolKind))); // Verify that no diagnostic is reported if the accessibility is wrong await TestMissingInRegularAndScriptAsync( -$@"class C -{{ - {camelCaseSymbol} -}}", new TestParameters(options: s_options.AccessibilitiesArePascalCase(ImmutableArray.Create(alternateAccessibility)))); + $$""" + class C + { + {{camelCaseSymbol}} + } + """, new TestParameters(options: s_options.AccessibilitiesArePascalCase(ImmutableArray.Create(alternateAccessibility)))); await TestInRegularAndScriptAsync( -$@"class C -{{ - {camelCaseSymbol} -}}", -$@"class C -{{ - {pascalCaseSymbol} -}}", options: s_options.AccessibilitiesArePascalCase(ImmutableArray.Create(accessibility))); + $$""" + class C + { + {{camelCaseSymbol}} + } + """, + $$""" + class C + { + {{pascalCaseSymbol}} + } + """, options: s_options.AccessibilitiesArePascalCase(ImmutableArray.Create(accessibility))); } [Fact] public async Task TestPascalCaseMethod_NameGetsCapitalized() { await TestInRegularAndScriptAsync( -@"class C -{ - void [|m|]() - { - } -}", -@"class C -{ - void M() - { - } -}", + """ + class C + { + void [|m|]() + { + } + } + """, + """ + class C + { + void M() + { + } + } + """, options: s_options.MethodNamesArePascalCase); } @@ -282,71 +322,83 @@ void M() public async Task TestPascalCaseMethod_ConstructorsAreIgnored() { await TestMissingInRegularAndScriptAsync( -@"class c -{ - public [|c|]() - { - } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + """ + class c + { + public [|c|]() + { + } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestPascalCaseMethod_PropertyAccessorsAreIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - public int P { [|get|]; set; } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + """ + class C + { + public int P { [|get|]; set; } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestPascalCaseMethod_IndexerNameIsIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - public int [|this|][int index] - { - get - { - return 1; - } - } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + """ + class C + { + public int [|this|][int index] + { + get + { + return 1; + } + } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestPascalCaseMethod_LocalFunctionIsIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - void [|f|]() - { - } - } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + """ + class C + { + void M() + { + void [|f|]() + { + } + } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestCamelCaseParameters() { await TestInRegularAndScriptAsync( -@"class C -{ - public void M(int [|X|]) - { - } -}", -@"class C -{ - public void M(int x) - { - } -}", + """ + class C + { + public void M(int [|X|]) + { + } + } + """, + """ + class C + { + public void M(int x) + { + } + } + """, options: s_options.ParameterNamesAreCamelCase); } @@ -354,20 +406,24 @@ public void M(int x) public async Task TestCamelCaseLocals_LocalDeclaration1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|X|]; - } -}", -@"class C -{ - void M() - { - int x; - } -}", + """ + class C + { + void M() + { + int [|X|]; + } + } + """, + """ + class C + { + void M() + { + int x; + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -375,20 +431,24 @@ void M() public async Task TestCamelCaseLocals_LocalDeclaration2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int X, [|Y|] = 0; - } -}", -@"class C -{ - void M() - { - int X, y = 0; - } -}", + """ + class C + { + void M() + { + int X, [|Y|] = 0; + } + } + """, + """ + class C + { + void M() + { + int X, y = 0; + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -396,24 +456,28 @@ void M() public async Task TestCamelCaseLocals_UsingVariable1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - using (object [|A|] = null) - { - } - } -}", -@"class C -{ - void M() - { - using (object a = null) - { - } - } -}", + """ + class C + { + void M() + { + using (object [|A|] = null) + { + } + } + } + """, + """ + class C + { + void M() + { + using (object a = null) + { + } + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -421,24 +485,28 @@ void M() public async Task TestCamelCaseLocals_UsingVariable2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - using (object A = null, [|B|] = null) - { - } - } -}", -@"class C -{ - void M() - { - using (object A = null, b = null) - { - } - } -}", + """ + class C + { + void M() + { + using (object A = null, [|B|] = null) + { + } + } + } + """, + """ + class C + { + void M() + { + using (object A = null, b = null) + { + } + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -446,24 +514,28 @@ void M() public async Task TestCamelCaseLocals_ForVariable1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - for (int [|I|] = 0, J = 0; I < J; ++I) - { - } - } -}", -@"class C -{ - void M() - { - for (int i = 0, J = 0; i < J; ++i) - { - } - } -}", + """ + class C + { + void M() + { + for (int [|I|] = 0, J = 0; I < J; ++I) + { + } + } + } + """, + """ + class C + { + void M() + { + for (int i = 0, J = 0; i < J; ++i) + { + } + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -471,24 +543,28 @@ void M() public async Task TestCamelCaseLocals_ForVariable2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - for (int I = 0, [|J|] = 0; I < J; ++J) - { - } - } -}", -@"class C -{ - void M() - { - for (int I = 0, j = 0; I < j; ++j) - { - } - } -}", + """ + class C + { + void M() + { + for (int I = 0, [|J|] = 0; I < J; ++J) + { + } + } + } + """, + """ + class C + { + void M() + { + for (int I = 0, j = 0; I < j; ++j) + { + } + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -496,24 +572,28 @@ void M() public async Task TestCamelCaseLocals_ForEachVariable() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - foreach (var [|X|] in new string[] { }) - { - } - } -}", -@"class C -{ - void M() - { - foreach (var x in new string[] { }) - { - } - } -}", + """ + class C + { + void M() + { + foreach (var [|X|] in new string[] { }) + { + } + } + } + """, + """ + class C + { + void M() + { + foreach (var x in new string[] { }) + { + } + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -521,32 +601,36 @@ void M() public async Task TestCamelCaseLocals_CatchVariable() { await TestInRegularAndScriptAsync( -@"using System; -class C -{ - void M() - { - try - { - } - catch (Exception [|Exception|]) - { - } - } -}", -@"using System; -class C -{ - void M() - { - try - { - } - catch (Exception exception) - { - } - } -}", + """ + using System; + class C + { + void M() + { + try + { + } + catch (Exception [|Exception|]) + { + } + } + } + """, + """ + using System; + class C + { + void M() + { + try + { + } + catch (Exception exception) + { + } + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -554,60 +638,68 @@ void M() public async Task TestCamelCaseLocals_CatchWithoutVariableIgnored() { await TestMissingInRegularAndScriptAsync( -@"using System; -class C -{ - void M() - { - try - { - } - catch ([|Exception|]) - { - } - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + using System; + class C + { + void M() + { + try + { + } + catch ([|Exception|]) + { + } + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestCamelCaseLocals_CatchWithoutDeclarationIgnored() { await TestMissingInRegularAndScriptAsync( -@"using System; -class C -{ - void M() - { - try - { - } - [|catch|] - { - } - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + using System; + class C + { + void M() + { + try + { + } + [|catch|] + { + } + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestCamelCaseLocals_Deconstruction1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - (int A, (string [|B|], var C)) = (0, (string.Empty, string.Empty)); - System.Console.WriteLine(A + B + C); - } -}", -@"class C -{ - void M() - { - (int A, (string b, var C)) = (0, (string.Empty, string.Empty)); - System.Console.WriteLine(A + b + C); - } -}", + """ + class C + { + void M() + { + (int A, (string [|B|], var C)) = (0, (string.Empty, string.Empty)); + System.Console.WriteLine(A + B + C); + } + } + """, + """ + class C + { + void M() + { + (int A, (string b, var C)) = (0, (string.Empty, string.Empty)); + System.Console.WriteLine(A + b + C); + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -615,22 +707,26 @@ void M() public async Task TestCamelCaseLocals_Deconstruction2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - var (A, (B, [|C|])) = (0, (string.Empty, string.Empty)); - System.Console.WriteLine(A + B + C); - } -}", -@"class C -{ - void M() - { - var (A, (B, [|c|])) = (0, (string.Empty, string.Empty)); - System.Console.WriteLine(A + B + c); - } -}", + """ + class C + { + void M() + { + var (A, (B, [|C|])) = (0, (string.Empty, string.Empty)); + System.Console.WriteLine(A + B + C); + } + } + """, + """ + class C + { + void M() + { + var (A, (B, [|c|])) = (0, (string.Empty, string.Empty)); + System.Console.WriteLine(A + B + c); + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -638,22 +734,26 @@ void M() public async Task TestCamelCaseLocals_ForEachDeconstruction1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - foreach ((int A, (string [|B|], var C)) in new[] { (0, (string.Empty, string.Empty)) }) - System.Console.WriteLine(A + B + C); - } -}", -@"class C -{ - void M() - { - foreach ((int A, (string b, var C)) in new[] { (0, (string.Empty, string.Empty)) }) - System.Console.WriteLine(A + b + C); - } -}", + """ + class C + { + void M() + { + foreach ((int A, (string [|B|], var C)) in new[] { (0, (string.Empty, string.Empty)) }) + System.Console.WriteLine(A + B + C); + } + } + """, + """ + class C + { + void M() + { + foreach ((int A, (string b, var C)) in new[] { (0, (string.Empty, string.Empty)) }) + System.Console.WriteLine(A + b + C); + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -661,22 +761,26 @@ void M() public async Task TestCamelCaseLocals_ForEachDeconstruction2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - foreach (var (A, (B, [|C|])) in new[] { (0, (string.Empty, string.Empty)) }) - System.Console.WriteLine(A + B + C); - } -}", -@"class C -{ - void M() - { - foreach (var (A, (B, c)) in new[] { (0, (string.Empty, string.Empty)) }) - System.Console.WriteLine(A + B + c); - } -}", + """ + class C + { + void M() + { + foreach (var (A, (B, [|C|])) in new[] { (0, (string.Empty, string.Empty)) }) + System.Console.WriteLine(A + B + C); + } + } + """, + """ + class C + { + void M() + { + foreach (var (A, (B, c)) in new[] { (0, (string.Empty, string.Empty)) }) + System.Console.WriteLine(A + B + c); + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -684,22 +788,26 @@ void M() public async Task TestCamelCaseLocals_OutVariable() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - if (int.TryParse(string.Empty, out var [|Value|])) - System.Console.WriteLine(Value); - } -}", -@"class C -{ - void M() - { - if (int.TryParse(string.Empty, out var value)) - System.Console.WriteLine(value); - } -}", + """ + class C + { + void M() + { + if (int.TryParse(string.Empty, out var [|Value|])) + System.Console.WriteLine(Value); + } + } + """, + """ + class C + { + void M() + { + if (int.TryParse(string.Empty, out var value)) + System.Console.WriteLine(value); + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -707,22 +815,26 @@ void M() public async Task TestCamelCaseLocals_PatternVariable() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - if (new object() is int [|Value|]) - System.Console.WriteLine(Value); - } -}", -@"class C -{ - void M() - { - if (new object() is int value) - System.Console.WriteLine(value); - } -}", + """ + class C + { + void M() + { + if (new object() is int [|Value|]) + System.Console.WriteLine(Value); + } + } + """, + """ + class C + { + void M() + { + if (new object() is int value) + System.Console.WriteLine(value); + } + } + """, options: s_options.LocalNamesAreCamelCase); } @@ -731,18 +843,20 @@ public async Task TestCamelCaseLocals_QueryFromClauseIgnored() { // This is an IRangeVariableSymbol, not ILocalSymbol await TestMissingInRegularAndScriptAsync( -@"using System.Linq; - -class C -{ - void M() - { - var squares = - from [|STRING|] in new string[] { } - let Number = int.Parse(STRING) - select Number * Number; - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + using System.Linq; + + class C + { + void M() + { + var squares = + from [|STRING|] in new string[] { } + let Number = int.Parse(STRING) + select Number * Number; + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] @@ -750,83 +864,97 @@ public async Task TestCamelCaseLocals_QueryLetClauseIgnored() { // This is an IRangeVariableSymbol, not ILocalSymbol await TestMissingInRegularAndScriptAsync( -@"using System.Linq; - -class C -{ - void M() - { - var squares = - from STRING in new string[] { } - let [|Number|] = int.Parse(STRING) - select Number * Number; - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + using System.Linq; + + class C + { + void M() + { + var squares = + from STRING in new string[] { } + let [|Number|] = int.Parse(STRING) + select Number * Number; + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestCamelCaseLocals_ParameterIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(int [|X|]) - { - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + class C + { + void M(int [|X|]) + { + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestCamelCaseLocals_TupleTypeElementNameIgnored1() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - (int [|A|], string B) tuple; - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + class C + { + void M() + { + (int [|A|], string B) tuple; + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestCamelCaseLocals_TupleTypeElementNameIgnored2() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - (int A, (string [|B|], string C)) tuple = (0, (string.Empty, string.Empty)); - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + class C + { + void M() + { + (int A, (string [|B|], string C)) tuple = (0, (string.Empty, string.Empty)); + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestCamelCaseLocals_TupleExpressionElementNameIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - var tuple = ([|A|]: 0, B: 0); - } -}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + """ + class C + { + void M() + { + var tuple = ([|A|]: 0, B: 0); + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact] public async Task TestUpperCaseConstants_ConstField() { await TestInRegularAndScriptAsync( -@"class C -{ - const int [|field|] = 0; -}", -@"class C -{ - const int FIELD = 0; -}", + """ + class C + { + const int [|field|] = 0; + } + """, + """ + class C + { + const int FIELD = 0; + } + """, options: s_options.ConstantsAreUpperCase); } @@ -834,20 +962,24 @@ await TestInRegularAndScriptAsync( public async Task TestUpperCaseConstants_ConstLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - const int local1 = 0, [|local2|] = 0; - } -}", -@"class C -{ - void M() - { - const int local1 = 0, LOCAL2 = 0; - } -}", + """ + class C + { + void M() + { + const int local1 = 0, [|local2|] = 0; + } + } + """, + """ + class C + { + void M() + { + const int local1 = 0, LOCAL2 = 0; + } + } + """, options: s_options.ConstantsAreUpperCase); } @@ -855,43 +987,51 @@ void M() public async Task TestUpperCaseConstants_NonConstFieldIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - readonly int [|field|] = 0; -}", new TestParameters(options: s_options.ConstantsAreUpperCase)); + """ + class C + { + readonly int [|field|] = 0; + } + """, new TestParameters(options: s_options.ConstantsAreUpperCase)); } [Fact] public async Task TestUpperCaseConstants_NonConstLocalIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int local1 = 0, [|local2|] = 0; - } -}", new TestParameters(options: s_options.ConstantsAreUpperCase)); + """ + class C + { + void M() + { + int local1 = 0, [|local2|] = 0; + } + } + """, new TestParameters(options: s_options.ConstantsAreUpperCase)); } [Fact] public async Task TestCamelCaseLocalsUpperCaseConstants_ConstLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - const int [|PascalCase|] = 0; - } -}", -@"class C -{ - void M() - { - const int PASCALCASE = 0; - } -}", + """ + class C + { + void M() + { + const int [|PascalCase|] = 0; + } + } + """, + """ + class C + { + void M() + { + const int PASCALCASE = 0; + } + } + """, options: s_options.LocalsAreCamelCaseConstantsAreUpperCase); } @@ -899,20 +1039,24 @@ void M() public async Task TestCamelCaseLocalsUpperCaseConstants_NonConstLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|PascalCase|] = 0; - } -}", -@"class C -{ - void M() - { - int pascalCase = 0; - } -}", + """ + class C + { + void M() + { + int [|PascalCase|] = 0; + } + } + """, + """ + class C + { + void M() + { + int pascalCase = 0; + } + } + """, options: s_options.LocalsAreCamelCaseConstantsAreUpperCase); } @@ -920,24 +1064,28 @@ void M() public async Task TestCamelCaseLocalFunctions() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - void [|F|]() - { - } - } -}", -@"class C -{ - void M() - { - void f() - { - } - } -}", + """ + class C + { + void M() + { + void [|F|]() + { + } + } + } + """, + """ + class C + { + void M() + { + void f() + { + } + } + } + """, options: s_options.LocalFunctionNamesAreCamelCase); } @@ -945,30 +1093,36 @@ void f() public async Task TestCamelCaseLocalFunctions_MethodIsIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void [|M|]() - { - } -}", new TestParameters(options: s_options.LocalFunctionNamesAreCamelCase)); + """ + class C + { + void [|M|]() + { + } + } + """, new TestParameters(options: s_options.LocalFunctionNamesAreCamelCase)); } [Fact] public async Task TestAsyncFunctions_AsyncMethod() { await TestInRegularAndScriptAsync( -@"class C -{ - async void [|M|]() - { - } -}", -@"class C -{ - async void MAsync() - { - } -}", + """ + class C + { + async void [|M|]() + { + } + } + """, + """ + class C + { + async void MAsync() + { + } + } + """, options: s_options.AsyncFunctionNamesEndWithAsync); } @@ -976,24 +1130,28 @@ async void MAsync() public async Task TestAsyncFunctions_AsyncLocalFunction() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - async void [|F|]() - { - } - } -}", -@"class C -{ - void M() - { - async void FAsync() - { - } - } -}", + """ + class C + { + void M() + { + async void [|F|]() + { + } + } + } + """, + """ + class C + { + void M() + { + async void FAsync() + { + } + } + } + """, options: s_options.AsyncFunctionNamesEndWithAsync); } @@ -1001,54 +1159,62 @@ async void FAsync() public async Task TestAsyncFunctions_NonAsyncMethodIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void [|M|]() - { - async void F() - { - } - } -}", new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); + """ + class C + { + void [|M|]() + { + async void F() + { + } + } + } + """, new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); } [Fact] public async Task TestAsyncFunctions_NonAsyncLocalFunctionIgnored() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - async void M() - { - void [|F|]() - { - } - } -}", new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); + """ + class C + { + async void M() + { + void [|F|]() + { + } + } + } + """, new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); } [Fact] public async Task TestPascalCaseMethod_InInterfaceWithImplicitImplementation() { await TestInRegularAndScriptAsync( -@"interface I -{ - void [|m|](); -} - -class C : I -{ - public void m() { } -}", -@"interface I -{ - void M(); -} - -class C : I -{ - public void M() { } -}", + """ + interface I + { + void [|m|](); + } + + class C : I + { + public void m() { } + } + """, + """ + interface I + { + void M(); + } + + class C : I + { + public void M() { } + } + """, options: s_options.MethodNamesArePascalCase); } @@ -1056,24 +1222,28 @@ public void M() { } public async Task TestPascalCaseMethod_InInterfaceWithExplicitImplementation() { await TestInRegularAndScriptAsync( -@"interface I -{ - void [|m|](); -} - -class C : I -{ - void I.m() { } -}", -@"interface I -{ - void M(); -} - -class C : I -{ - void I.M() { } -}", + """ + interface I + { + void [|m|](); + } + + class C : I + { + void I.m() { } + } + """, + """ + interface I + { + void M(); + } + + class C : I + { + void I.M() { } + } + """, options: s_options.MethodNamesArePascalCase); } @@ -1081,56 +1251,62 @@ void I.M() { } public async Task TestPascalCaseMethod_NotInImplicitInterfaceImplementation() { await TestMissingInRegularAndScriptAsync( -@"interface I -{ - void m(); -} + """ + interface I + { + void m(); + } -class C : I -{ - public void [|m|]() { } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + class C : I + { + public void [|m|]() { } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestPascalCaseMethod_NotInExplicitInterfaceImplementation() { await TestMissingInRegularAndScriptAsync( -@"interface I -{ - void m(); -} + """ + interface I + { + void m(); + } -class C : I -{ - void I.[|m|]() { } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + class C : I + { + void I.[|m|]() { } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestPascalCaseMethod_InAbstractType() { await TestInRegularAndScriptAsync( -@" -abstract class C -{ - public abstract void [|m|](); -} - -class D : C -{ - public override void m() { } -}", -@" -abstract class C -{ - public abstract void M(); -} - -class D : C -{ - public override void M() { } -}", + """ + abstract class C + { + public abstract void [|m|](); + } + + class D : C + { + public override void m() { } + } + """, + """ + abstract class C + { + public abstract void M(); + } + + class D : C + { + public override void M() { } + } + """, options: s_options.MethodNamesArePascalCase); } @@ -1138,42 +1314,45 @@ public override void M() { } public async Task TestPascalCaseMethod_NotInAbstractMethodImplementation() { await TestMissingInRegularAndScriptAsync( -@" -abstract class C -{ - public abstract void m(); -} + """ + abstract class C + { + public abstract void m(); + } -class D : C -{ - public override void [|m|]() { } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + class D : C + { + public override void [|m|]() { } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact] public async Task TestPascalCaseProperty_InInterface() { await TestInRegularAndScriptAsync( -@" -interface I -{ - int [|p|] { get; set; } -} - -class C : I -{ - public int p { get { return 1; } set { } } -}", -@" -interface I -{ - int P { get; set; } -} - -class C : I -{ - public int P { get { return 1; } set { } } -}", + """ + interface I + { + int [|p|] { get; set; } + } + + class C : I + { + public int p { get { return 1; } set { } } + } + """, + """ + interface I + { + int P { get; set; } + } + + class C : I + { + public int P { get { return 1; } set { } } + } + """, options: s_options.PropertyNamesArePascalCase); } @@ -1181,44 +1360,46 @@ class C : I public async Task TestPascalCaseProperty_NotInImplicitInterfaceImplementation() { await TestMissingInRegularAndScriptAsync( -@" -interface I -{ - int p { get; set; } -} + """ + interface I + { + int p { get; set; } + } -class C : I -{ - public int [|p|] { get { return 1; } set { } } -}", new TestParameters(options: s_options.PropertyNamesArePascalCase)); + class C : I + { + public int [|p|] { get { return 1; } set { } } + } + """, new TestParameters(options: s_options.PropertyNamesArePascalCase)); } [Fact] public async Task TestPascalCaseMethod_OverrideInternalMethod() { await TestMissingInRegularAndScriptAsync( -@" -abstract class C -{ - internal abstract void m(); -} + """ + abstract class C + { + internal abstract void m(); + } -class D : C -{ - internal override void [|m|]() { } -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + class D : C + { + internal override void [|m|]() { } + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19106")] public async Task TestMissingOnSymbolsWithNoName() { await TestMissingInRegularAndScriptAsync( -@" -namespace Microsoft.CodeAnalysis.Host -{ - internal interface -[|}|] -", new TestParameters(options: s_options.InterfaceNamesStartWithI)); + """ + namespace Microsoft.CodeAnalysis.Host + { + internal interface + [|}|] + """, new TestParameters(options: s_options.InterfaceNamesStartWithI)); } #if CODE_STYLE @@ -1279,10 +1460,12 @@ public async Task TestRefactorNotifyInterfaceNamesStartWithI() [WorkItem("https://github.com/dotnet/roslyn/issues/38513")] public async Task TestRefactorNotifyTypeParameterNamesStartWithT() { - var markup = @"public class A -{ - void DoOtherThing<[|arg|]>() { } -}"; + var markup = """ + public class A + { + void DoOtherThing<[|arg|]>() { } + } + """; var testParameters = new TestParameters(options: s_options.TypeParameterNamesStartWithT); using var workspace = CreateWorkspaceFromOptions(markup, testParameters); @@ -1311,12 +1494,14 @@ await TestMissingInRegularAndScriptAsync( public async Task TestRecordConstructorParameter_NoDiagnosticWhenCorrect() { await TestMissingInRegularAndScriptAsync( -@"record Foo(int MyInt) -{ - public Foo(string [|p_myString|]) : this(1) - { - } -}", + """ + record Foo(int MyInt) + { + public Foo(string [|p_myString|]) : this(1) + { + } + } + """, new TestParameters(options: s_options.MergeStyles(s_options.PropertyNamesArePascalCase, s_options.ParameterNamesAreCamelCaseWithPUnderscorePrefix))); } @@ -1338,12 +1523,14 @@ await TestInRegularAndScriptAsync( public async Task TestDiscardParameterAsync(string identifier) { await TestMissingInRegularAndScriptAsync( -$@"class C -{{ - void M(int [|{identifier}|]) - {{ - }} -}}", new TestParameters(options: s_options.ParameterNamesAreCamelCase)); + $$""" + class C + { + void M(int [|{{identifier}}|]) + { + } + } + """, new TestParameters(options: s_options.ParameterNamesAreCamelCase)); } [Theory] @@ -1355,65 +1542,70 @@ void M(int [|{identifier}|]) public async Task TestDiscardLocalAsync(string identifier) { await TestMissingInRegularAndScriptAsync( -$@"class C -{{ - void M() - {{ - int [|{identifier}|] = 0; - }} -}}", new TestParameters(options: s_options.LocalNamesAreCamelCase)); + $$""" + class C + { + void M() + { + int [|{{identifier}}|] = 0; + } + } + """, new TestParameters(options: s_options.LocalNamesAreCamelCase)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49535")] public async Task TestGlobalDirectiveAsync() { await TestMissingInRegularAndScriptAsync( -@" -interface I -{ - int X { get; } -} + """ + interface I + { + int X { get; } + } -class C : I -{ - int [|global::I.X|] => 0; -}", new TestParameters(options: s_options.PropertyNamesArePascalCase)); + class C : I + { + int [|global::I.X|] => 0; + } + """, new TestParameters(options: s_options.PropertyNamesArePascalCase)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/50734")] public async Task TestAsyncEntryPoint() { - await TestMissingInRegularAndScriptAsync(@" -using System.Threading.Tasks; + await TestMissingInRegularAndScriptAsync(""" + using System.Threading.Tasks; -class C -{ - static async Task [|Main|]() - { - await Task.Delay(0); - } -}", new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); + class C + { + static async Task [|Main|]() + { + await Task.Delay(0); + } + } + """, new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49648")] public async Task TestAsyncEntryPoint_TopLevel() { - await TestMissingInRegularAndScriptAsync(@" -using System.Threading.Tasks; + await TestMissingInRegularAndScriptAsync(""" + using System.Threading.Tasks; -[|await Task.Delay(0);|] -", new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); + [|await Task.Delay(0);|] + """, new TestParameters(options: s_options.AsyncFunctionNamesEndWithAsync)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/51727")] public async Task TestExternAsync() { await TestMissingInRegularAndScriptAsync( -@" -class C -{ - static extern void [|some_p_invoke()|]; -}", new TestParameters(options: s_options.MethodNamesArePascalCase)); + """ + class C + { + static extern void [|some_p_invoke()|]; + } + """, new TestParameters(options: s_options.MethodNamesArePascalCase)); } } } diff --git a/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchExpressionTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchExpressionTests_FixAllTests.cs index dd9d171904026..0d928d22972c9 100644 --- a/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchExpressionTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchExpressionTests_FixAllTests.cs @@ -15,151 +15,153 @@ public partial class PopulateSwitchExpressionTests [Fact] public async Task TestFixAllInDocument() { - var input = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e {|FixAllInDocument:|}switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - -"; + var input = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e {|FixAllInDocument:|}switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + """; - var expected = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - -"; + var expected = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -167,139 +169,141 @@ void Method() [Fact] public async Task TestFixAllInProject() { - var input = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e {|FixAllInProject:|}switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - -"; + var input = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e {|FixAllInProject:|}switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + """; - var expected = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - _ = e switch - { - MyEnum.Fizz => 1, - MyEnum.Buzz => 2, - MyEnum.FizzBuzz => 3, - }; - } - } -} - - -"; + var expected = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + _ = e switch + { + MyEnum.Fizz => 1, + MyEnum.Buzz => 2, + MyEnum.FizzBuzz => 3, + }; + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -307,156 +311,158 @@ void Method() [Fact] public async Task TestFixAllInSolution() { - var input = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum1 - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum1.Fizz; - _ = e {|FixAllInSolution:|}switch - { - MyEnum1.Fizz => 1, - MyEnum1.Buzz => 2, - MyEnum1.FizzBuzz => 3, - }; - } - } -} - - -namespace ConsoleApplication1 -{ - enum MyEnum2 - { - Fizz, Buzz, FizzBuzz - } - class MyClass2 - { - void Method() - { - var e = MyEnum2.Fizz; - _ = e switch - { - MyEnum2.Fizz => 1, - MyEnum2.Buzz => 2, - MyEnum2.FizzBuzz => 3, - }; - } - } -} - - - - -namespace ConsoleApplication2 -{ - enum MyEnum3 - { - Fizz, Buzz, FizzBuzz - } - class MyClass3 - { - void Method() - { - var e = MyEnum3.Fizz; - _ = e switch - { - MyEnum3.Fizz => 1, - MyEnum3.Buzz => 2, - MyEnum3.FizzBuzz => 3, - }; - } - } -} - - -"; + var input = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum1 + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum1.Fizz; + _ = e {|FixAllInSolution:|}switch + { + MyEnum1.Fizz => 1, + MyEnum1.Buzz => 2, + MyEnum1.FizzBuzz => 3, + }; + } + } + } + + + namespace ConsoleApplication1 + { + enum MyEnum2 + { + Fizz, Buzz, FizzBuzz + } + class MyClass2 + { + void Method() + { + var e = MyEnum2.Fizz; + _ = e switch + { + MyEnum2.Fizz => 1, + MyEnum2.Buzz => 2, + MyEnum2.FizzBuzz => 3, + }; + } + } + } + + + + + namespace ConsoleApplication2 + { + enum MyEnum3 + { + Fizz, Buzz, FizzBuzz + } + class MyClass3 + { + void Method() + { + var e = MyEnum3.Fizz; + _ = e switch + { + MyEnum3.Fizz => 1, + MyEnum3.Buzz => 2, + MyEnum3.FizzBuzz => 3, + }; + } + } + } + + + + """; - var expected = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum1 - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum1.Fizz; - _ = e switch - { - MyEnum1.Fizz => 1, - MyEnum1.Buzz => 2, - MyEnum1.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - } - } -} - - -namespace ConsoleApplication1 -{ - enum MyEnum2 - { - Fizz, Buzz, FizzBuzz - } - class MyClass2 - { - void Method() - { - var e = MyEnum2.Fizz; - _ = e switch - { - MyEnum2.Fizz => 1, - MyEnum2.Buzz => 2, - MyEnum2.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - } - } -} - - - - -namespace ConsoleApplication2 -{ - enum MyEnum3 - { - Fizz, Buzz, FizzBuzz - } - class MyClass3 - { - void Method() - { - var e = MyEnum3.Fizz; - _ = e switch - { - MyEnum3.Fizz => 1, - MyEnum3.Buzz => 2, - MyEnum3.FizzBuzz => 3, - _ => throw new System.NotImplementedException(), - }; - } - } -} - - -"; + var expected = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum1 + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum1.Fizz; + _ = e switch + { + MyEnum1.Fizz => 1, + MyEnum1.Buzz => 2, + MyEnum1.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + } + } + } + + + namespace ConsoleApplication1 + { + enum MyEnum2 + { + Fizz, Buzz, FizzBuzz + } + class MyClass2 + { + void Method() + { + var e = MyEnum2.Fizz; + _ = e switch + { + MyEnum2.Fizz => 1, + MyEnum2.Buzz => 2, + MyEnum2.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + } + } + } + + + + + namespace ConsoleApplication2 + { + enum MyEnum3 + { + Fizz, Buzz, FizzBuzz + } + class MyClass3 + { + void Method() + { + var e = MyEnum3.Fizz; + _ = e switch + { + MyEnum3.Fizz => 1, + MyEnum3.Buzz => 2, + MyEnum3.FizzBuzz => 3, + _ => throw new System.NotImplementedException(), + }; + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } diff --git a/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchStatementTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchStatementTests_FixAllTests.cs index 776352b983412..f10c7c1c0ec48 100644 --- a/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchStatementTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/PopulateSwitch/PopulateSwitchStatementTests_FixAllTests.cs @@ -18,161 +18,163 @@ public partial class PopulateSwitchStatementTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocument() { - var input = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - {|FixAllInDocument:|}switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - -"; + var input = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + {|FixAllInDocument:|}switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + """; - var expected = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - default: - break; - } - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - default: - break; - } - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - -"; + var expected = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + default: + break; + } + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + default: + break; + } + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -182,147 +184,149 @@ void Method() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProject() { - var input = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - {|FixAllInProject:|}switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - -"; + var input = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + {|FixAllInProject:|}switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + """; - var expected = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - default: - break; - } - } - } -} - - -namespace ConsoleApplication1 -{ - class MyClass2 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - default: - break; - } - } - } -} - - - - -namespace ConsoleApplication1 -{ - class MyClass3 - { - void Method() - { - var e = MyEnum.Fizz; - switch (e) - { - case MyEnum.Fizz: - case MyEnum.Buzz: - case MyEnum.FizzBuzz: - break; - } - } - } -} - - -"; + var expected = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + default: + break; + } + } + } + } + + + namespace ConsoleApplication1 + { + class MyClass2 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + default: + break; + } + } + } + } + + + + + namespace ConsoleApplication1 + { + class MyClass3 + { + void Method() + { + var e = MyEnum.Fizz; + switch (e) + { + case MyEnum.Fizz: + case MyEnum.Buzz: + case MyEnum.FizzBuzz: + break; + } + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -332,165 +336,167 @@ void Method() [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution() { - var input = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum1 - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum1.Fizz; - {|FixAllInSolution:|}switch (e) - { - case MyEnum1.Fizz: - case MyEnum1.Buzz: - case MyEnum1.FizzBuzz: - break; - } - } - } -} - - -namespace ConsoleApplication1 -{ - enum MyEnum2 - { - Fizz, Buzz, FizzBuzz - } - class MyClass2 - { - void Method() - { - var e = MyEnum2.Fizz; - switch (e) - { - case MyEnum2.Fizz: - case MyEnum2.Buzz: - case MyEnum2.FizzBuzz: - break; - } - } - } -} - - - - -namespace ConsoleApplication2 -{ - enum MyEnum3 - { - Fizz, Buzz, FizzBuzz - } - class MyClass3 - { - void Method() - { - var e = MyEnum3.Fizz; - switch (e) - { - case MyEnum3.Fizz: - case MyEnum3.Buzz: - case MyEnum3.FizzBuzz: - break; - } - } - } -} - - -"; + var input = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum1 + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum1.Fizz; + {|FixAllInSolution:|}switch (e) + { + case MyEnum1.Fizz: + case MyEnum1.Buzz: + case MyEnum1.FizzBuzz: + break; + } + } + } + } + + + namespace ConsoleApplication1 + { + enum MyEnum2 + { + Fizz, Buzz, FizzBuzz + } + class MyClass2 + { + void Method() + { + var e = MyEnum2.Fizz; + switch (e) + { + case MyEnum2.Fizz: + case MyEnum2.Buzz: + case MyEnum2.FizzBuzz: + break; + } + } + } + } + + + + + namespace ConsoleApplication2 + { + enum MyEnum3 + { + Fizz, Buzz, FizzBuzz + } + class MyClass3 + { + void Method() + { + var e = MyEnum3.Fizz; + switch (e) + { + case MyEnum3.Fizz: + case MyEnum3.Buzz: + case MyEnum3.FizzBuzz: + break; + } + } + } + } + + + + """; - var expected = @" - - - -namespace ConsoleApplication1 -{ - enum MyEnum1 - { - Fizz, Buzz, FizzBuzz - } - class MyClass1 - { - void Method() - { - var e = MyEnum1.Fizz; - switch (e) - { - case MyEnum1.Fizz: - case MyEnum1.Buzz: - case MyEnum1.FizzBuzz: - break; - default: - break; - } - } - } -} - - -namespace ConsoleApplication1 -{ - enum MyEnum2 - { - Fizz, Buzz, FizzBuzz - } - class MyClass2 - { - void Method() - { - var e = MyEnum2.Fizz; - switch (e) - { - case MyEnum2.Fizz: - case MyEnum2.Buzz: - case MyEnum2.FizzBuzz: - break; - default: - break; - } - } - } -} - - - - -namespace ConsoleApplication2 -{ - enum MyEnum3 - { - Fizz, Buzz, FizzBuzz - } - class MyClass3 - { - void Method() - { - var e = MyEnum3.Fizz; - switch (e) - { - case MyEnum3.Fizz: - case MyEnum3.Buzz: - case MyEnum3.FizzBuzz: - break; - default: - break; - } - } - } -} - - -"; + var expected = """ + + + + namespace ConsoleApplication1 + { + enum MyEnum1 + { + Fizz, Buzz, FizzBuzz + } + class MyClass1 + { + void Method() + { + var e = MyEnum1.Fizz; + switch (e) + { + case MyEnum1.Fizz: + case MyEnum1.Buzz: + case MyEnum1.FizzBuzz: + break; + default: + break; + } + } + } + } + + + namespace ConsoleApplication1 + { + enum MyEnum2 + { + Fizz, Buzz, FizzBuzz + } + class MyClass2 + { + void Method() + { + var e = MyEnum2.Fizz; + switch (e) + { + case MyEnum2.Fizz: + case MyEnum2.Buzz: + case MyEnum2.FizzBuzz: + break; + default: + break; + } + } + } + } + + + + + namespace ConsoleApplication2 + { + enum MyEnum3 + { + Fizz, Buzz, FizzBuzz + } + class MyClass3 + { + void Method() + { + var e = MyEnum3.Fizz; + switch (e) + { + case MyEnum3.Fizz: + case MyEnum3.Buzz: + case MyEnum3.FizzBuzz: + break; + default: + break; + } + } + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } diff --git a/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests.cs b/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests.cs index e746f62150e7e..3bf8e5f0d1c20 100644 --- a/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests.cs +++ b/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests.cs @@ -2017,8 +2017,7 @@ public void Bar() CodeStyleOptions2.QualifyFieldAccess); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/22776")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22776")] [WorkItem("https://github.com/dotnet/roslyn/issues/64374")] public async Task DoReportToQualify_InObjectInitializer2() { diff --git a/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests_FixAllTests.cs index 6dfbaac9741ab..b796f7f7fa14d 100644 --- a/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/QualifyMemberAccess/QualifyMemberAccessTests_FixAllTests.cs @@ -20,77 +20,79 @@ public partial class QualifyMemberAccessTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution_QualifyMemberAccess() { - var input = @" - - - -using System; + var input = """ + + + + using System; -class C -{ - int Property { get; set; } - int OtherProperty { get; set; } + class C + { + int Property { get; set; } + int OtherProperty { get; set; } - void M() - { - {|FixAllInSolution:Property|} = 1; - var x = OtherProperty; - } -} - - -using System; + void M() + { + {|FixAllInSolution:Property|} = 1; + var x = OtherProperty; + } + } + + + using System; -class D -{ - string StringProperty { get; set; } - int field; + class D + { + string StringProperty { get; set; } + int field; - void N() - { - StringProperty = string.Empty; - field = 0; // ensure this doesn't get qualified - } -} - - -"; + void N() + { + StringProperty = string.Empty; + field = 0; // ensure this doesn't get qualified + } + } + + + + """; - var expected = @" - - - -using System; + var expected = """ + + + + using System; -class C -{ - int Property { get; set; } - int OtherProperty { get; set; } + class C + { + int Property { get; set; } + int OtherProperty { get; set; } - void M() - { - this.Property = 1; - var x = this.OtherProperty; - } -} - - -using System; + void M() + { + this.Property = 1; + var x = this.OtherProperty; + } + } + + + using System; -class D -{ - string StringProperty { get; set; } - int field; + class D + { + string StringProperty { get; set; } + int field; - void N() - { - this.StringProperty = string.Empty; - field = 0; // ensure this doesn't get qualified - } -} - - -"; + void N() + { + this.StringProperty = string.Empty; + field = 0; // ensure this doesn't get qualified + } + } + + + + """; await TestInRegularAndScriptAsync( initialMarkup: input, diff --git a/src/Analyzers/CSharp/Tests/RemoveInKeyword/RemoveInKeywordCodeFixProviderTests.cs b/src/Analyzers/CSharp/Tests/RemoveInKeyword/RemoveInKeywordCodeFixProviderTests.cs index 0f1223aed6354..c4c07a92a359a 100644 --- a/src/Analyzers/CSharp/Tests/RemoveInKeyword/RemoveInKeywordCodeFixProviderTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveInKeyword/RemoveInKeywordCodeFixProviderTests.cs @@ -164,24 +164,28 @@ void N(int i) public async Task TestRemoveInKeywordWithTrivia(string original, string expected) { await TestInRegularAndScript1Async( -$@"class App -{{ - void M(int i) {{ }} - void N(int i) - {{ - M({original}); - }} + $$""" + class App + { + void M(int i) { } + void N(int i) + { + M({{original}}); + } -}}", -$@"class App -{{ - void M(int i) {{ }} - void N(int i) - {{ - M({expected}); - }} + } + """, + $$""" + class App + { + void M(int i) { } + void N(int i) + { + M({{expected}}); + } -}}"); + } + """); } [Fact] diff --git a/src/Analyzers/CSharp/Tests/RemoveNewModifier/RemoveNewModifierCodeFixProviderTests.cs b/src/Analyzers/CSharp/Tests/RemoveNewModifier/RemoveNewModifierCodeFixProviderTests.cs index 5ec0ec2e134d5..fce023cb0738a 100644 --- a/src/Analyzers/CSharp/Tests/RemoveNewModifier/RemoveNewModifierCodeFixProviderTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveNewModifier/RemoveNewModifierCodeFixProviderTests.cs @@ -140,14 +140,18 @@ enum E2 { } private Task TestRemoveNewModifierCodeFixAsync(string original, string expected) { return TestInRegularAndScript1Async( -$@"class App -{{ - {original} -}}", -$@"class App -{{ - {expected} -}}"); + $$""" + class App + { + {{original}} + } + """, + $$""" + class App + { + {{expected}} + } + """); } } } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs index 2d66befb77cd8..197522d93ae3d 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.cs @@ -5612,21 +5612,22 @@ static class Program public async Task DoNotRemoveCastOnInvalidUnaryOperatorEnumValue1(string op) { var source = -$@" -enum Sign - {{ - Positive = 1, - Negative = -1 - }} + $$""" + enum Sign + { + Positive = 1, + Negative = -1 + } - class T - {{ - void Goo() - {{ - Sign mySign = Sign.Positive; - Sign invertedSign = (Sign) ( {op}((int) mySign) ); - }} - }}"; + class T + { + void Goo() + { + Sign mySign = Sign.Positive; + Sign invertedSign = (Sign) ( {{op}}((int) mySign) ); + } + } + """; await VerifyCS.VerifyCodeFixAsync(source, source); } @@ -5637,21 +5638,22 @@ void Goo() public async Task DoNotRemoveCastOnInvalidUnaryOperatorEnumValue2(string op) { var source = -$@" -enum Sign - {{ - Positive = 1, - Negative = -1 - }} + $$""" + enum Sign + { + Positive = 1, + Negative = -1 + } - class T - {{ - void Goo() - {{ - Sign mySign = Sign.Positive; - Sign invertedSign = (Sign) ( {op}(int) mySign ); - }} - }}"; + class T + { + void Goo() + { + Sign mySign = Sign.Positive; + Sign invertedSign = (Sign) ( {{op}}(int) mySign ); + } + } + """; await VerifyCS.VerifyCodeFixAsync(source, source); } @@ -13029,28 +13031,28 @@ static T M2(object o) where T : Delegate [InlineData("Func")] public async Task ConvertingMethodGroupToObject_CastIsUnnecessary(string type) { - var code = $@" -using System; + var code = $$""" + using System; -class C -{{ - static {type} M(object o) - {{ - return ({type})[|(object)|]o.ToString; - }} -}} -"; - var fixedCode = $@" -using System; + class C + { + static {{type}} M(object o) + { + return ({{type}})[|(object)|]o.ToString; + } + } + """; + var fixedCode = $$""" + using System; -class C -{{ - static {type} M(object o) - {{ - return o.ToString; - }} -}} -"; + class C + { + static {{type}} M(object o) + { + return o.ToString; + } + } + """; await new VerifyCS.Test { TestCode = code, @@ -13775,4 +13777,27 @@ void M2() ReferenceAssemblies = ReferenceAssemblies.Net.Net80, }.RunAsync(); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71926")] + public async Task NecessaryDelegateCast() + { + await new VerifyCS.Test + { + TestCode = """ + using System; + using System.Runtime.CompilerServices; + + class C + { + static void Main(string[] args) + { + var main = (Delegate)Main; // IDE0004: Cast is redundant. + var x = Unsafe.As(ref main); + } + } + """, + LanguageVersion = LanguageVersion.CSharp12, + ReferenceAssemblies = ReferenceAssemblies.Net.Net80, + }.RunAsync(); + } } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_FixAllTests.cs index f545701a5851d..f47e31b7beaf2 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests_FixAllTests.cs @@ -30,165 +30,167 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocument() { - var input = @" - - - -class Program -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = {|FixAllInDocument:(int)0|}; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - - // cast removal that leads to parenthesis removal - var prog = new Program(); - ((Program)prog).F(); - } -} - - -class Program2 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - - // cast removal that leads to parenthesis removal - var prog = new Program(); - ((Program)prog).F(); - } -} - - - - -class Program3 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - - // cast removal that leads to parenthesis removal - var prog = new Program(); - ((Program)prog).F(); - } -} - - -"; - - var expected = @" - - - -class Program -{ - private char f = 'c'; - public void F(int x = 0) - { - // unnecessary casts - int y = 0; - bool z = true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? s1 : (object)s2; - - // cast removal that leads to parenthesis removal - var prog = new Program(); - prog.F(); - } -} - - -class Program2 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - - // cast removal that leads to parenthesis removal - var prog = new Program(); - ((Program)prog).F(); - } -} - - - - -class Program3 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - - // cast removal that leads to parenthesis removal - var prog = new Program(); - ((Program)prog).F(); - } -} - - -"; + var input = """ + + + + class Program + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = {|FixAllInDocument:(int)0|}; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + + // cast removal that leads to parenthesis removal + var prog = new Program(); + ((Program)prog).F(); + } + } + + + class Program2 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + + // cast removal that leads to parenthesis removal + var prog = new Program(); + ((Program)prog).F(); + } + } + + + + + class Program3 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + + // cast removal that leads to parenthesis removal + var prog = new Program(); + ((Program)prog).F(); + } + } + + + + """; + + var expected = """ + + + + class Program + { + private char f = 'c'; + public void F(int x = 0) + { + // unnecessary casts + int y = 0; + bool z = true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? s1 : (object)s2; + + // cast removal that leads to parenthesis removal + var prog = new Program(); + prog.F(); + } + } + + + class Program2 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + + // cast removal that leads to parenthesis removal + var prog = new Program(); + ((Program)prog).F(); + } + } + + + + + class Program3 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + + // cast removal that leads to parenthesis removal + var prog = new Program(); + ((Program)prog).F(); + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -198,141 +200,143 @@ public void F(int x = (int)0) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProject() { - var input = @" - - - -class Program -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = {|FixAllInProject:(int)0|}; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - -class Program2 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - - - -class Program3 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - -"; - - var expected = @" - - - -class Program -{ - private char f = 'c'; - public void F(int x = 0) - { - // unnecessary casts - int y = 0; - bool z = true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? s1 : (object)s2; - } -} - - -class Program2 -{ - private char f = 'c'; - public void F(int x = 0) - { - // unnecessary casts - int y = 0; - bool z = true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? s1 : (object)s2; - } -} - - - - -class Program3 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - -"; + var input = """ + + + + class Program + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = {|FixAllInProject:(int)0|}; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + class Program2 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + + + class Program3 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + + """; + + var expected = """ + + + + class Program + { + private char f = 'c'; + public void F(int x = 0) + { + // unnecessary casts + int y = 0; + bool z = true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? s1 : (object)s2; + } + } + + + class Program2 + { + private char f = 'c'; + public void F(int x = 0) + { + // unnecessary casts + int y = 0; + bool z = true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? s1 : (object)s2; + } + } + + + + + class Program3 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -342,141 +346,143 @@ public void F(int x = (int)0) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution() { - var input = @" - - - -class Program -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = {|FixAllInSolution:(int)0|}; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - -class Program2 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - - - -class Program3 -{ - private char f = (char)'c'; - public void F(int x = (int)0) - { - // unnecessary casts - int y = (int)0; - bool z = (bool)true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? (object)s1 : (object)s2; - } -} - - -"; - - var expected = @" - - - -class Program -{ - private char f = 'c'; - public void F(int x = 0) - { - // unnecessary casts - int y = 0; - bool z = true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? s1 : (object)s2; - } -} - - -class Program2 -{ - private char f = 'c'; - public void F(int x = 0) - { - // unnecessary casts - int y = 0; - bool z = true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? s1 : (object)s2; - } -} - - - - -class Program3 -{ - private char f = 'c'; - public void F(int x = 0) - { - // unnecessary casts - int y = 0; - bool z = true; - - // required cast - long l = 1; - int y = (int)l; - - // required cast after cast removal in same statement - string s1 = null, s2 = null; - var s3 = z ? s1 : (object)s2; - } -} - - -"; + var input = """ + + + + class Program + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = {|FixAllInSolution:(int)0|}; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + class Program2 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + + + class Program3 + { + private char f = (char)'c'; + public void F(int x = (int)0) + { + // unnecessary casts + int y = (int)0; + bool z = (bool)true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? (object)s1 : (object)s2; + } + } + + + + """; + + var expected = """ + + + + class Program + { + private char f = 'c'; + public void F(int x = 0) + { + // unnecessary casts + int y = 0; + bool z = true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? s1 : (object)s2; + } + } + + + class Program2 + { + private char f = 'c'; + public void F(int x = 0) + { + // unnecessary casts + int y = 0; + bool z = true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? s1 : (object)s2; + } + } + + + + + class Program3 + { + private char f = 'c'; + public void F(int x = 0) + { + // unnecessary casts + int y = 0; + bool z = true; + + // required cast + long l = 1; + int y = (int)l; + + // required cast after cast removal in same statement + string s1 = null, s2 = null; + var s3 = z ? s1 : (object)s2; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryImports/RemoveUnnecessaryImportsTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryImports/RemoveUnnecessaryImportsTests_FixAllTests.cs index 60ff95baaede8..822d28691c047 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryImports/RemoveUnnecessaryImportsTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryImports/RemoveUnnecessaryImportsTests_FixAllTests.cs @@ -32,74 +32,76 @@ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProvider [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocument() { - var input = @" - - - -{|FixAllInDocument:using System; -using System.Collections.Generic;|} - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; + var input = """ + + + + {|FixAllInDocument:using System; + using System.Collections.Generic;|} + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -109,73 +111,75 @@ class Program3 [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProject() { - var input = @" - - - -{|FixAllInProject:using System; -using System.Collections.Generic;|} - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - public Int32 x; -} - - -using System; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; + var input = """ + + + + {|FixAllInProject:using System; + using System.Collections.Generic;|} + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + public Int32 x; + } + + + using System; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -185,74 +189,76 @@ class Program3 [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProjectSkipsGeneratedCode() { - var input = @" - - - -{|FixAllInProject:using System; -using System.Collections.Generic;|} - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; + var input = """ + + + + {|FixAllInProject:using System; + using System.Collections.Generic;|} + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -262,72 +268,74 @@ class Program3 [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution() { - var input = @" - - - -{|FixAllInSolution:using System; -using System.Collections.Generic;|} - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - public Int32 x; -} - - -using System; - -class Program2 -{ - public Int32 x; -} - - - - -using System; - -class Program3 -{ - public Int32 x; -} - - -"; + var input = """ + + + + {|FixAllInSolution:using System; + using System.Collections.Generic;|} + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + public Int32 x; + } + + + using System; + + class Program2 + { + public Int32 x; + } + + + + + using System; + + class Program3 + { + public Int32 x; + } + + + + """; await TestInRegularAndScriptAsync(input, expected); } @@ -337,40 +345,41 @@ class Program3 [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingMember_NotApplicable() { - var input = @" - - - -{|FixAllInContainingMember:using System; -using System.Collections.Generic;|} - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; + var input = """ + + + + {|FixAllInContainingMember:using System; + using System.Collections.Generic;|} + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; await TestMissingInRegularAndScriptAsync(input); } @@ -380,40 +389,41 @@ class Program3 [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInContainingType_NotApplicable() { - var input = @" - - - -{|FixAllInContainingType:using System; -using System.Collections.Generic;|} - -class Program -{ - public Int32 x; -} - - -using System; -using System.Collections.Generic; - -class Program2 -{ - public Int32 x; -} - - - - -using System; -using System.Collections.Generic; - -class Program3 -{ - public Int32 x; -} - - -"; + var input = """ + + + + {|FixAllInContainingType:using System; + using System.Collections.Generic;|} + + class Program + { + public Int32 x; + } + + + using System; + using System.Collections.Generic; + + class Program2 + { + public Int32 x; + } + + + + + using System; + using System.Collections.Generic; + + class Program3 + { + public Int32 x; + } + + + + """; await TestMissingInRegularAndScriptAsync(input); } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnreachableCode/RemoveUnreachableCodeTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnreachableCode/RemoveUnreachableCodeTests.cs index f0bc029b515dc..55a51d3334d8d 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnreachableCode/RemoveUnreachableCodeTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnreachableCode/RemoveUnreachableCodeTests.cs @@ -1053,5 +1053,30 @@ public class C { } LanguageVersion = LanguageVersion.CSharp9, }.RunAsync(); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72024")] + public async Task TestIncompleteBinaryExpression() + { + await new VerifyCS.Test + { + TestCode = """ + public class C { } + + {|CS8803:throw new System.Exception();|} + [|1+1|]{|CS1002:|} + """, + FixedCode = """ + public class C { } + + {|CS8803:throw new System.Exception();|} + + """, + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + }, + LanguageVersion = LanguageVersion.CSharp9, + }.RunAsync(); + } } } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedMembers/RemoveUnusedMembersTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedMembers/RemoveUnusedMembersTests.cs index 5bfaa34cb1bde..af3a950e24d70 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnusedMembers/RemoveUnusedMembersTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnusedMembers/RemoveUnusedMembersTests.cs @@ -53,10 +53,12 @@ public void M() [InlineData("private protected")] public async Task NonPrivateField(string accessibility) { - var code = $@"class MyClass -{{ - {accessibility} int _goo; -}}"; + var code = $$""" + class MyClass + { + {{accessibility}} int _goo; + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -69,10 +71,12 @@ public async Task NonPrivateField(string accessibility) [InlineData("private protected")] public async Task NonPrivateFieldWithConstantInitializer(string accessibility) { - var code = $@"class MyClass -{{ - {accessibility} int _goo = 0; -}}"; + var code = $$""" + class MyClass + { + {{accessibility}} int _goo = 0; + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -85,11 +89,13 @@ public async Task NonPrivateFieldWithConstantInitializer(string accessibility) [InlineData("private protected")] public async Task NonPrivateFieldWithNonConstantInitializer(string accessibility) { - var code = $@"class MyClass -{{ - {accessibility} int _goo = _goo2; - private static readonly int _goo2 = 0; -}}"; + var code = $$""" + class MyClass + { + {{accessibility}} int _goo = _goo2; + private static readonly int _goo2 = 0; + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -102,10 +108,12 @@ public async Task NonPrivateFieldWithNonConstantInitializer(string accessibility [InlineData("private protected")] public async Task NonPrivateMethod(string accessibility) { - var code = $@"class MyClass -{{ - {accessibility} void M() {{ }} -}}"; + var code = $$""" + class MyClass + { + {{accessibility}} void M() { } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -118,10 +126,12 @@ public async Task NonPrivateMethod(string accessibility) [InlineData("private protected")] public async Task NonPrivateProperty(string accessibility) { - var code = $@"class MyClass -{{ - {accessibility} int P {{ get; }} -}}"; + var code = $$""" + class MyClass + { + {{accessibility}} int P { get; } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -134,11 +144,13 @@ public async Task NonPrivateProperty(string accessibility) [InlineData("private protected")] public async Task NonPrivateIndexer(string accessibility) { - var code = $@"class MyClass -{{ - {accessibility} - int this[int arg] {{ get {{ return 0; }} set {{ }} }} -}}"; + var code = $$""" + class MyClass + { + {{accessibility}} + int this[int arg] { get { return 0; } set { } } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -151,12 +163,14 @@ public async Task NonPrivateIndexer(string accessibility) [InlineData("private protected")] public async Task NonPrivateEvent(string accessibility) { - var code = $@"using System; + var code = $$""" + using System; -class MyClass -{{ - {accessibility} event EventHandler RaiseCustomEvent; -}}"; + class MyClass + { + {{accessibility}} event EventHandler RaiseCustomEvent; + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -2173,14 +2187,18 @@ public async Task MultipleFields_AllUnused_FixOne( [CombinatorialValues("[|_bar|]", "[|_bar|] = 2")] string secondField, [CombinatorialValues(0, 1)] int diagnosticIndex) { - var source = $@"class MyClass -{{ - private int {firstField}, {secondField}; -}}"; - var fixedSource = $@"class MyClass -{{ - private int {(diagnosticIndex == 0 ? secondField : firstField)}; -}}"; + var source = $$""" + class MyClass + { + private int {{firstField}}, {{secondField}}; + } + """; + var fixedSource = $$""" + class MyClass + { + private int {{(diagnosticIndex == 0 ? secondField : firstField)}}; + } + """; var batchFixedSource = """ class MyClass { @@ -2789,13 +2807,15 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) [InlineData(@"[System.Runtime.InteropServices.ComUnregisterFunctionAttribute]")] public async Task MethodsWithSpecialAttributes(string attribute) { - var code = $@"class C -{{ - {attribute} - private void M() - {{ - }} -}}"; + var code = $$""" + class C + { + {{attribute}} + private void M() + { + } + } + """; await VerifyCS.VerifyCodeFixAsync(code, code); } @@ -3164,23 +3184,25 @@ private C(int i) { } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/62856")] public async Task DontWarnForAwaiterMethods() { - const string code = @"using System; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; + const string code = """ + using System; + using System.Runtime.CompilerServices; + using System.Threading.Tasks; -class C : ICriticalNotifyCompletion -{ - public async Task M() - { - await this; - } + class C : ICriticalNotifyCompletion + { + public async Task M() + { + await this; + } - private C GetAwaiter() => this; - private bool IsCompleted => false; - private void GetResult() { } - public void OnCompleted(Action continuation) => Task.Run(continuation); - public void UnsafeOnCompleted(Action continuation) => Task.Run(continuation); -}"; + private C GetAwaiter() => this; + private bool IsCompleted => false; + private void GetResult() { } + public void OnCompleted(Action continuation) => Task.Run(continuation); + public void UnsafeOnCompleted(Action continuation) => Task.Run(continuation); + } + """; await VerifyCS.VerifyAnalyzerAsync(code); } @@ -3188,27 +3210,31 @@ private void GetResult() { } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/62856")] public async Task WarnForAwaiterMethodsNotImplementingInterface() { - const string code = @"using System; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; + const string code = """ + using System; + using System.Runtime.CompilerServices; + using System.Threading.Tasks; -class C -{ - private C [|GetAwaiter|]() => this; - private bool [|IsCompleted|] => false; - private void [|GetResult|]() { } - public void OnCompleted(Action continuation) => Task.Run(continuation); - public void UnsafeOnCompleted(Action continuation) => Task.Run(continuation); -}"; - const string fixedCode = @"using System; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; + class C + { + private C [|GetAwaiter|]() => this; + private bool [|IsCompleted|] => false; + private void [|GetResult|]() { } + public void OnCompleted(Action continuation) => Task.Run(continuation); + public void UnsafeOnCompleted(Action continuation) => Task.Run(continuation); + } + """; + const string fixedCode = """ + using System; + using System.Runtime.CompilerServices; + using System.Threading.Tasks; -class C -{ - public void OnCompleted(Action continuation) => Task.Run(continuation); - public void UnsafeOnCompleted(Action continuation) => Task.Run(continuation); -}"; + class C + { + public void OnCompleted(Action continuation) => Task.Run(continuation); + public void UnsafeOnCompleted(Action continuation) => Task.Run(continuation); + } + """; await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs index 2cf3a3705c821..bf7a305de685f 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs @@ -83,12 +83,14 @@ void M(int [|p|]) public async Task Parameter_Unused_NonPrivate_NotApplicable(string typeAccessibility, string methodAccessibility) { await TestDiagnosticMissingAsync( -$@"{typeAccessibility} class C -{{ - {methodAccessibility} void M(int [|p|]) - {{ - }} -}}", NonPublicMethodsOnly); + $$""" + {{typeAccessibility}} class C + { + {{methodAccessibility}} void M(int [|p|]) + { + } + } + """, NonPublicMethodsOnly); } [Theory] @@ -101,12 +103,14 @@ await TestDiagnosticMissingAsync( public async Task Parameter_Unused_NonPublicMethod(string typeAccessibility, string methodAccessibility) { await TestDiagnosticsAsync( -$@"{typeAccessibility} class C -{{ - {methodAccessibility} void M(int [|p|]) - {{ - }} -}}", NonPublicMethodsOnly, + $$""" + {{typeAccessibility}} class C + { + {{methodAccessibility}} void M(int [|p|]) + { + } + } + """, NonPublicMethodsOnly, Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)); } @@ -1123,13 +1127,15 @@ public void MyHandler(object [|obj|], CustomEventArgs args) public async Task Parameter_MethodsWithSpecialAttributes(string attribute) { await TestDiagnosticMissingAsync( -$@"class C -{{ - {attribute} - void M(int [|p|]) - {{ - }} -}}"); + $$""" + class C + { + {{attribute}} + void M(int [|p|]) + { + } + } + """); } [Theory] @@ -1138,19 +1144,20 @@ void M(int [|p|]) public async Task Parameter_ConstructorsWithSpecialAttributes(string attributeNamespace, string attributeName) { await TestDiagnosticMissingAsync( -$@" -namespace {attributeNamespace} -{{ - public class {attributeName} : System.Attribute {{ }} -}} + $$""" + namespace {{attributeNamespace}} + { + public class {{attributeName}} : System.Attribute { } + } -class C -{{ - [{attributeNamespace}.{attributeName}()] - public C(int [|p|]) - {{ - }} -}}"); + class C + { + [{{attributeNamespace}}.{{attributeName}}()] + public C(int [|p|]) + { + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32133")] @@ -1877,23 +1884,27 @@ public void Method() public async Task Test_PrimaryConstructor1() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C(int [|a100|]) -{ -}"); + class C(int [|a100|]) + { + } + """); } [Fact, WorkItem(67013, "https://github.com/dotnet/roslyn/issues/67013")] public async Task Test_PrimaryConstructor2() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C(int [|a100|]) : Object() -{ - int M1() => a100; -}"); + class C(int [|a100|]) : Object() + { + int M1() => a100; + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70276")] diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs index 6689d880a521b..710a013428e3c 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs @@ -50,15 +50,17 @@ public void TestStandardProperty(AnalyzerProperty property) public async Task Initialization_Suppressed() { var source = -@"class C -{ - int M() - { - int x = 1; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int x = 1; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -75,16 +77,18 @@ int M() public async Task Assignment_Suppressed() { var source = -@"class C -{ - int M() - { - int x; - x = 1; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int x; + x = 1; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -103,24 +107,28 @@ int M() public async Task Initialization_ConstantValue(object option) { var source = -@"class C -{ - int M() - { - int {|IDE0059:x|} = 1; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int {|IDE0059:x|} = 1; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - int M() - { - int x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -139,34 +147,38 @@ int M() public async Task Initialization_ConstantValue_DoNotCopyLeadingTriviaDirectives(object option) { var source = -@"class C { - void M() - { - #region - int value = 3; - #endregion - - int? {|IDE0059:x|} = null; - int y = value + value; - - x = y; - System.Console.WriteLine(x); - } -}"; + """ + class C { + void M() + { + #region + int value = 3; + #endregion + + int? {|IDE0059:x|} = null; + int y = value + value; + + x = y; + System.Console.WriteLine(x); + } + } + """; var fixedSource = -@"class C { - void M() - { - #region - int value = 3; + """ + class C { + void M() + { + #region + int value = 3; - #endregion - int y = value + value; + #endregion + int y = value + value; - int? x = y; - System.Console.WriteLine(x); - } -}"; + int? x = y; + System.Console.WriteLine(x); + } + } + """; await new VerifyCS.Test { @@ -183,24 +195,28 @@ void M() public async Task Initialization_ConstantValue_RemoveUnusedParametersSuppressed() { var source = -@"class C -{ - int M() - { - int {|IDE0059:x|} = 1; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int {|IDE0059:x|} = 1; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - int M() - { - int x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -217,24 +233,28 @@ int M() public async Task Initialization_ConstantValue_RemoveUnusedParametersNotApplicable() { var source = -@"class C -{ - public int M(int {|IDE0060:z|}) - { - int {|IDE0059:x|} = 1; - x = 2; - return x; - } -}"; + """ + class C + { + public int M(int {|IDE0060:z|}) + { + int {|IDE0059:x|} = 1; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - public int M(int {|IDE0060:z|}) - { - int x = 2; - return x; - } -}"; + """ + class C + { + public int M(int {|IDE0060:z|}) + { + int x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -253,26 +273,30 @@ public int M(int {|IDE0060:z|}) public async Task Assignment_ConstantValue(object option) { var source = -@"class C -{ - int M() - { - int x; - {|IDE0059:x|} = 1; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int x; + {|IDE0059:x|} = 1; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - int M() - { - int x; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int x; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -291,21 +315,25 @@ int M() public async Task Assignment_ConstantValue_NoReads(object option) { var source = -@"class C -{ - void M() - { - int x; - {|IDE0059:x|} = 1; - } -}"; + """ + class C + { + void M() + { + int x; + {|IDE0059:x|} = 1; + } + } + """; var fixedSource = -@"class C -{ - void M() - { - } -}"; + """ + class C + { + void M() + { + } + } + """; await new VerifyCS.Test { @@ -322,26 +350,30 @@ void M() public async Task Assignment_NonConstantValue_NoReads_PreferDiscard() { var source = -@"class C -{ - void M() - { - int x; - {|IDE0059:x|} = M2(); - } + """ + class C + { + void M() + { + int x; + {|IDE0059:x|} = M2(); + } - int M2() => 0; -}"; + int M2() => 0; + } + """; var fixedSource = -@"class C -{ - void M() - { - _ = M2(); - } + """ + class C + { + void M() + { + _ = M2(); + } - int M2() => 0; -}"; + int M2() => 0; + } + """; await new VerifyCS.Test { @@ -358,16 +390,18 @@ void M() public async Task Assignment_NonConstantValue_NoReads_PreferUnusedLocal() { var source = -@"class C -{ - void M() - { - int x; - x = M2(); - } + """ + class C + { + void M() + { + int x; + x = M2(); + } - int M2() => 0; -}"; + int M2() => 0; + } + """; await new VerifyCS.Test { @@ -386,24 +420,28 @@ void M() public async Task Initialization_NonConstantValue_ParameterReference(object option) { var source = -@"class C -{ - int M(int p) - { - int {|IDE0059:x|} = p; - x = 2; - return x; - } -}"; + """ + class C + { + int M(int p) + { + int {|IDE0059:x|} = p; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - int M(int {|IDE0060:p|}) - { - int x = 2; - return x; - } -}"; + """ + class C + { + int M(int {|IDE0060:p|}) + { + int x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -422,26 +460,30 @@ int M(int {|IDE0060:p|}) public async Task Assignment_NonConstantValue_ParameterReference(object option) { var source = -@"class C -{ - int M(int p) - { - int x; - {|IDE0059:x|} = p; - x = 2; - return x; - } -}"; + """ + class C + { + int M(int p) + { + int x; + {|IDE0059:x|} = p; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - int M(int {|IDE0060:p|}) - { - int x; - x = 2; - return x; - } -}"; + """ + class C + { + int M(int {|IDE0060:p|}) + { + int x; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -461,29 +503,34 @@ public async Task Initialization_NonConstantValue_LocalReference( [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - int M() - { - int local = 0; - int {|IDE0059:x|} = local; - x = 2; - return x; - } -}"; + """ + class C + { + int M() + { + int local = 0; + int {|IDE0059:x|} = local; + x = 2; + return x; + } + } + """; var (fixedSource, iterations) = testBehaviors switch { CodeFixTestBehaviors.None => -(@"class C +(""" +class C { int M() { int x = 2; return x; } -}", iterations: 2), +} +""", iterations: 2), CodeFixTestBehaviors.FixOne => -(@"class C +(""" +class C { int M() { @@ -491,7 +538,8 @@ int M() int x = 2; return x; } -}", iterations: 1), +} +""", iterations: 1), _ => throw ExceptionUtilities.Unreachable(), }; @@ -516,31 +564,36 @@ public async Task Assignment_NonConstantValue_LocalReference( [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C + """ + class C + { + int M() + { + int local = 0; + int x; + {|IDE0059:x|} = local; + x = 2; + return x; + } + } + """; + var (fixedSource, iterations) = testBehaviors switch + { + CodeFixTestBehaviors.None => +(""" +class C { int M() { - int local = 0; int x; - {|IDE0059:x|} = local; x = 2; return x; } -}"; - var (fixedSource, iterations) = testBehaviors switch - { - CodeFixTestBehaviors.None => -(@"class C -{ - int M() - { - int x; - x = 2; - return x; - } -}", iterations: 2), +} +""", iterations: 2), CodeFixTestBehaviors.FixOne => -(@"class C +(""" +class C { int M() { @@ -549,7 +602,8 @@ int M() x = 2; return x; } -}", iterations: 1), +} +""", iterations: 1), _ => throw ExceptionUtilities.Unreachable(), }; @@ -573,24 +627,28 @@ int M() public async Task Initialization_NonConstantValue_DefaultExpression(object option) { var source = -@"struct C -{ - C M() - { - C {|IDE0059:c|} = default(C); - c = new C(); - return c; - } -}"; + """ + struct C + { + C M() + { + C {|IDE0059:c|} = default(C); + c = new C(); + return c; + } + } + """; var fixedSource = -@"struct C -{ - C M() - { - C c = new C(); - return c; - } -}"; + """ + struct C + { + C M() + { + C c = new C(); + return c; + } + } + """; await new VerifyCS.Test { @@ -609,24 +667,28 @@ C M() public async Task Initialization_NonConstantValue_CastExpression(object option) { var source = -@"struct C -{ - C M(object obj) - { - C {|IDE0059:c|} = (C)obj; - c = new C(); - return c; - } -}"; + """ + struct C + { + C M(object obj) + { + C {|IDE0059:c|} = (C)obj; + c = new C(); + return c; + } + } + """; var fixedSource = -@"struct C -{ - C M(object {|IDE0060:obj|}) - { - C c = new C(); - return c; - } -}"; + """ + struct C + { + C M(object {|IDE0060:obj|}) + { + C c = new C(); + return c; + } + } + """; await new VerifyCS.Test { @@ -645,26 +707,30 @@ C M(object {|IDE0060:obj|}) public async Task Initialization_NonConstantValue_FieldReferenceWithThisReceiver(object option) { var source = -@"class C -{ - private int field; - int M() - { - int {|IDE0059:x|} = field; - x = 2; - return x; - } -}"; + """ + class C + { + private int field; + int M() + { + int {|IDE0059:x|} = field; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - private int field; - int M() - { - int x = 2; - return x; - } -}"; + """ + class C + { + private int field; + int M() + { + int x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -683,28 +749,32 @@ int M() public async Task Assignment_NonConstantValue_FieldReferenceWithNullReceiver(object option) { var source = -@"class C -{ - private static int field; - int M() - { - int x; - {|IDE0059:x|} = field; - x = 2; - return x; - } -}"; + """ + class C + { + private static int field; + int M() + { + int x; + {|IDE0059:x|} = field; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - private static int field; - int M() - { - int x; - x = 2; - return x; - } -}"; + """ + class C + { + private static int field; + int M() + { + int x; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -723,29 +793,33 @@ int M() public async Task Assignment_NonConstantValue_FieldReferenceWithReceiver(object option, string fix) { var source = -@"class C -{ - private int field; - int M(C c) - { - int x; - {|IDE0059:x|} = c.field; - x = 2; - return x; - } -}"; + """ + class C + { + private int field; + int M(C c) + { + int x; + {|IDE0059:x|} = c.field; + x = 2; + return x; + } + } + """; var fixedSource = -$@"class C -{{ - private int field; - int M(C c) - {{ - int x; - {fix} = c.field; - x = 2; - return x; - }} -}}"; + $$""" + class C + { + private int field; + int M(C c) + { + int x; + {{fix}} = c.field; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -764,29 +838,33 @@ int M(C c) public async Task Initialization_NonConstantValue_PropertyReference(object option, string fix) { var source = -@"class C -{ - private int Property { get { throw new System.Exception(); } } - int M() - { - int x; - {|IDE0059:x|} = Property; - x = 2; - return x; - } -}"; + """ + class C + { + private int Property { get { throw new System.Exception(); } } + int M() + { + int x; + {|IDE0059:x|} = Property; + x = 2; + return x; + } + } + """; var fixedSource = -$@"class C -{{ - private int Property {{ get {{ throw new System.Exception(); }} }} - int M() - {{ - int x; - {fix} = Property; - x = 2; - return x; - }} -}}"; + $$""" + class C + { + private int Property { get { throw new System.Exception(); } } + int M() + { + int x; + {{fix}} = Property; + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -805,29 +883,33 @@ int M() public async Task Initialization_NonConstantValue_MethodInvocation(object option, string fix) { var source = -@"class C -{ - int M() - { - int {|IDE0059:x|} = M2(); - x = 2; - return x; - } + """ + class C + { + int M() + { + int {|IDE0059:x|} = M2(); + x = 2; + return x; + } - int M2() => 0; -}"; + int M2() => 0; + } + """; var fixedSource = -$@"class C -{{ - int M() - {{ - {fix} = M2(); - int x = 2; - return x; - }} + $$""" + class C + { + int M() + { + {{fix}} = M2(); + int x = 2; + return x; + } - int M2() => 0; -}}"; + int M2() => 0; + } + """; await new VerifyCS.Test { @@ -845,29 +927,33 @@ public async Task Initialization_NonConstantValue_PreferDiscard_CSharp6() { // Discard not supported in C# 6.0, so we fallback to unused local variable. var source = -@"class C -{ - int M() - { - int {|IDE0059:x|} = M2(); - x = 2; - return x; - } + """ + class C + { + int M() + { + int {|IDE0059:x|} = M2(); + x = 2; + return x; + } - int M2() => 0; -}"; + int M2() => 0; + } + """; var fixedSource = -@"class C -{ - int M() - { - int unused = M2(); - int x = 2; - return x; - } + """ + class C + { + int M() + { + int unused = M2(); + int x = 2; + return x; + } - int M2() => 0; -}"; + int M2() => 0; + } + """; await new VerifyCS.Test { @@ -887,31 +973,35 @@ int M() public async Task Assignment_NonConstantValue_MethodInvocation(object option, string fix) { var source = -@"class C -{ - int M() - { - int x; - {|IDE0059:x|} = M2(); - x = 2; - return x; - } + """ + class C + { + int M() + { + int x; + {|IDE0059:x|} = M2(); + x = 2; + return x; + } - int M2() => 0; -}"; + int M2() => 0; + } + """; var fixedSource = -$@"class C -{{ - int M() - {{ - int x; - {fix} = M2(); - x = 2; - return x; - }} + $$""" + class C + { + int M() + { + int x; + {{fix}} = M2(); + x = 2; + return x; + } - int M2() => 0; -}}"; + int M2() => 0; + } + """; await new VerifyCS.Test { @@ -930,24 +1020,28 @@ int M() public async Task Assignment_NonConstantValue_ImplicitConversion(object option) { var source = -@"class C -{ - int M(int {|IDE0060:x|}, short s) - { - {|IDE0059:x|} = s; - x = 2; - return x; - } -}"; + """ + class C + { + int M(int {|IDE0060:x|}, short s) + { + {|IDE0059:x|} = s; + x = 2; + return x; + } + } + """; var fixedSource = -@"class C -{ - int M(int {|IDE0060:x|}, short {|IDE0060:s|}) - { - x = 2; - return x; - } -}"; + """ + class C + { + int M(int {|IDE0060:x|}, short {|IDE0060:s|}) + { + x = 2; + return x; + } + } + """; await new VerifyCS.Test { @@ -966,45 +1060,49 @@ int M(int {|IDE0060:x|}, short {|IDE0060:s|}) public async Task Assignment_NonConstantValue_UserDefinedConversion(object option, string fix) { var source = -@"class C -{ - int M(int {|IDE0060:x|}, C c) - { - {|IDE0059:x|} = (int)c; - x = 2; - return x; - } + """ + class C + { + int M(int {|IDE0060:x|}, C c) + { + {|IDE0059:x|} = (int)c; + x = 2; + return x; + } - public static explicit operator int(C {|IDE0060:c|}) - { - return 0; - } + public static explicit operator int(C {|IDE0060:c|}) + { + return 0; + } - public static explicit operator C(int {|IDE0060:i|}) - { - return default(C); - } -}"; + public static explicit operator C(int {|IDE0060:i|}) + { + return default(C); + } + } + """; var fixedSource = -$@"class C -{{ - int M(int {{|IDE0060:x|}}, C c) - {{ - {fix} = (int)c; - x = 2; - return x; - }} - - public static explicit operator int(C {{|IDE0060:c|}}) - {{ - return 0; - }} + $$""" + class C + { + int M(int {|IDE0060:x|}, C c) + { + {{fix}} = (int)c; + x = 2; + return x; + } - public static explicit operator C(int {{|IDE0060:i|}}) - {{ - return default(C); - }} -}}"; + public static explicit operator int(C {|IDE0060:c|}) + { + return 0; + } + + public static explicit operator C(int {|IDE0060:i|}) + { + return default(C); + } + } + """; await new VerifyCS.Test { @@ -1024,20 +1122,23 @@ public async Task NestedAssignment_ConstantValue( [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - int M(int {|IDE0060:x|}, int {|IDE0060:y|}) - { - {|IDE0059:y|} = {|IDE0059:x|} = 1; - x = 2; - return x; - } -}"; + """ + class C + { + int M(int {|IDE0060:x|}, int {|IDE0060:y|}) + { + {|IDE0059:y|} = {|IDE0059:x|} = 1; + x = 2; + return x; + } + } + """; var (fixedSource, iterations) = ((UnusedValuePreference)option, testBehaviors) switch { (UnusedValuePreference.DiscardVariable, CodeFixTestBehaviors.None) => -(@"class C +(""" +class C { int M(int {|IDE0060:x|}, int {|IDE0060:y|}) { @@ -1045,18 +1146,22 @@ int M(int {|IDE0060:x|}, int {|IDE0060:y|}) x = 2; return x; } -}", iterations: 2), +} +""", iterations: 2), (UnusedValuePreference.UnusedLocalVariable, CodeFixTestBehaviors.None) => -(@"class C +(""" +class C { int M(int {|IDE0060:x|}, int {|IDE0060:y|}) { x = 2; return x; } -}", iterations: 3), +} +""", iterations: 3), (_, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck) => -(@"class C +(""" +class C { int M(int {|IDE0060:x|}, int {|IDE0060:y|}) { @@ -1064,7 +1169,8 @@ int M(int {|IDE0060:x|}, int {|IDE0060:y|}) x = 2; return x; } -}", iterations: 1), +} +""", iterations: 1), _ => throw ExceptionUtilities.Unreachable(), }; @@ -1096,70 +1202,80 @@ public async Task NestedAssignment_NonConstantValue( [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - int M(int {|IDE0060:x|}, int {|IDE0060:y|}) - { - {|IDE0059:y|} = {|IDE0059:x|} = M2(); - x = 2; - return x; - } + """ + class C + { + int M(int {|IDE0060:x|}, int {|IDE0060:y|}) + { + {|IDE0059:y|} = {|IDE0059:x|} = M2(); + x = 2; + return x; + } - int M2() => 0; -}"; + int M2() => 0; + } + """; var fixedSource = ((UnusedValuePreference)option, testBehaviors) switch { (UnusedValuePreference.DiscardVariable, CodeFixTestBehaviors.None) => -@"class C -{ - int M(int {|IDE0060:x|}, int {|IDE0060:y|}) - { - _ = _ = M2(); - x = 2; - return x; - } + """ + class C + { + int M(int {|IDE0060:x|}, int {|IDE0060:y|}) + { + _ = _ = M2(); + x = 2; + return x; + } - int M2() => 0; -}", + int M2() => 0; + } + """, (UnusedValuePreference.DiscardVariable, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck) => -@"class C -{ - int M(int {|IDE0060:x|}, int {|IDE0060:y|}) - { - {|IDE0059:y|} = _ = M2(); - x = 2; - return x; - } + """ + class C + { + int M(int {|IDE0060:x|}, int {|IDE0060:y|}) + { + {|IDE0059:y|} = _ = M2(); + x = 2; + return x; + } - int M2() => 0; -}", + int M2() => 0; + } + """, (UnusedValuePreference.UnusedLocalVariable, CodeFixTestBehaviors.None) => -@"class C -{ - int M(int {|IDE0060:x|}, int {|IDE0060:y|}) - { - int unused1; - int unused = unused1 = M2(); - x = 2; - return x; - } + """ + class C + { + int M(int {|IDE0060:x|}, int {|IDE0060:y|}) + { + int unused1; + int unused = unused1 = M2(); + x = 2; + return x; + } - int M2() => 0; -}", + int M2() => 0; + } + """, (UnusedValuePreference.UnusedLocalVariable, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck) => -@"class C -{ - int M(int {|IDE0060:x|}, int {|IDE0060:y|}) - { - int unused; - {|IDE0059:y|} = unused = M2(); - x = 2; - return x; - } + """ + class C + { + int M(int {|IDE0060:x|}, int {|IDE0060:y|}) + { + int unused; + {|IDE0059:y|} = unused = M2(); + x = 2; + return x; + } - int M2() => 0; -}", + int M2() => 0; + } + """, _ => throw ExceptionUtilities.Unreachable(), }; @@ -1188,17 +1304,19 @@ int M(int {|IDE0060:x|}, int {|IDE0060:y|}) public async Task ReadAndWriteInSameExpression_MethodInvocation(object option) { var source = -@"class C -{ - int M() - { - int x = 1; - x = M2(x); - return x; - } + """ + class C + { + int M() + { + int x = 1; + x = M2(x); + return x; + } - int M2(int x) => x; -}"; + int M2(int x) => x; + } + """; await new VerifyCS.Test { @@ -1220,25 +1338,29 @@ public async Task IncrementOrDecrementOperator_ValueUsed_SameStatement( { var (prefix, postfix) = applyAsPrefix ? (@operator, "") : ("", @operator); var source = -$@"class C -{{ - void M(int x) - {{ - var {{|#0:y|}} = {prefix}x{postfix}; - }} -}}"; + $$""" + class C + { + void M(int x) + { + var {|#0:y|} = {{prefix}}x{{postfix}}; + } + } + """; var fixedSource = (UnusedValuePreference)option switch { UnusedValuePreference.UnusedLocalVariable => source, UnusedValuePreference.DiscardVariable => -$@"class C -{{ - void M(int x) - {{ - _ = {prefix}x{postfix}; - }} -}}", + $$""" + class C + { + void M(int x) + { + _ = {{prefix}}x{{postfix}}; + } + } + """, _ => throw ExceptionUtilities.Unreachable(), }; @@ -1271,14 +1393,16 @@ public async Task IncrementOrDecrementOperator_ValueUsed_LaterStatement( { var (prefix, postfix) = applyAsPrefix ? (@operator, "") : ("", @operator); var source = -$@"class C -{{ - int M(int x) - {{ - {prefix}x{postfix}; - return x; - }} -}}"; + $$""" + class C + { + int M(int x) + { + {{prefix}}x{{postfix}}; + return x; + } + } + """; await new VerifyCS.Test { @@ -1300,20 +1424,24 @@ public async Task IncrementOrDecrementOperator_ValueUnused( { var (prefix, postfix) = applyAsPrefix ? (@operator, "") : ("", @operator); var source = -$@"class C -{{ - void M(int x) - {{ - {prefix}{{|IDE0059:x|}}{postfix}; - }} -}}"; + $$""" + class C + { + void M(int x) + { + {{prefix}}{|IDE0059:x|}{{postfix}}; + } + } + """; var fixedSource = -@"class C -{ - void M(int {|IDE0060:x|}) - { - } -}"; + """ + class C + { + void M(int {|IDE0060:x|}) + { + } + } + """; await new VerifyCS.Test { @@ -1333,29 +1461,33 @@ public async Task CompoundAssignmentOperator_ValueUsed_SameStatement( [CombinatorialValues(UnusedValuePreference.DiscardVariable, UnusedValuePreference.UnusedLocalVariable)] object option) { var source = -$@"class C -{{ - void M(int x) - {{ - var {{|#0:y|}} = x += {rightHandSide}; - }} + $$""" + class C + { + void M(int x) + { + var {|#0:y|} = x += {{rightHandSide}}; + } - int M2() => 0; -}}"; + int M2() => 0; + } + """; var fixedSource = (UnusedValuePreference)option switch { UnusedValuePreference.UnusedLocalVariable => source, UnusedValuePreference.DiscardVariable => -$@"class C -{{ - void M(int x) - {{ - _ = x += {rightHandSide}; - }} - - int M2() => 0; -}}", + $$""" + class C + { + void M(int x) + { + _ = x += {{rightHandSide}}; + } + + int M2() => 0; + } + """, _ => throw ExceptionUtilities.Unreachable(), }; @@ -1386,16 +1518,18 @@ public async Task CompoundAssignmentOperator_ValueUsed_LaterStatement( [CombinatorialValues(UnusedValuePreference.DiscardVariable, UnusedValuePreference.UnusedLocalVariable)] object option) { var source = -$@"class C -{{ - int M(int x) - {{ - x += {rightHandSide}; - return x; - }} + $$""" + class C + { + int M(int x) + { + x += {{rightHandSide}}; + return x; + } - int M2() => 0; -}}"; + int M2() => 0; + } + """; await new VerifyCS.Test { @@ -1415,16 +1549,18 @@ public async Task CompoundLogicalOrOperator_ValueUsed_LaterStatement( [CombinatorialValues(UnusedValuePreference.DiscardVariable, UnusedValuePreference.UnusedLocalVariable)] object option) { var source = -$@"class C -{{ - bool M(bool x) - {{ - x |= {rightHandSide} && {rightHandSide}; - return x; - }} + $$""" + class C + { + bool M(bool x) + { + x |= {{rightHandSide}} && {{rightHandSide}}; + return x; + } - bool M2() => true; -}}"; + bool M2() => true; + } + """; await new VerifyCS.Test { @@ -1444,17 +1580,19 @@ public async Task CompoundLogicalOrOperator_ValueUsed_LaterStatement_02( [CombinatorialValues(UnusedValuePreference.DiscardVariable, UnusedValuePreference.UnusedLocalVariable)] object option) { var source = -$@"class C -{{ - bool M() - {{ - bool x = false; - x |= {rightHandSide} && {rightHandSide}; - return x; - }} + $$""" + class C + { + bool M() + { + bool x = false; + x |= {{rightHandSide}} && {{rightHandSide}}; + return x; + } - bool M2() => true; -}}"; + bool M2() => true; + } + """; await new VerifyCS.Test { @@ -1473,19 +1611,23 @@ bool M() public async Task CompoundAssignmentOperator_ValueNotUsed_ConstantValue(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M(int x) - { - [|x|] += 1; - } -}", -@"class C -{ - int M(int x) - { - } -}", optionName); + """ + class C + { + int M(int x) + { + [|x|] += 1; + } + } + """, + """ + class C + { + int M(int x) + { + } + } + """, optionName); } [Theory] @@ -1494,24 +1636,28 @@ int M(int x) public async Task CompoundAssignmentOperator_ValueNotUsed_NonConstantValue(string optionName, string fix) { await TestInRegularAndScriptAsync( -$@"class C -{{ - int M(int x) - {{ - [|x|] += M2(); - }} + $$""" + class C + { + int M(int x) + { + [|x|] += M2(); + } - int M2() => 0; -}}", -$@"class C -{{ - int M(int x) - {{ - {fix} = M2(); - }} + int M2() => 0; + } + """, + $$""" + class C + { + int M(int x) + { + {{fix}} = M2(); + } - int M2() => 0; -}}", optionName); + int M2() => 0; + } + """, optionName); } [Theory] @@ -1520,17 +1666,19 @@ int M(int x) public async Task NullCoalescing_ReadWrite(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - C M() - { - C [|x|] = M2(); - x = x ?? new C(); - return x; - } + """ + class C + { + C M() + { + C [|x|] = M2(); + x = x ?? new C(); + return x; + } - C M2() => null; -}", optionName); + C M2() => null; + } + """, optionName); } [Theory] @@ -1539,17 +1687,19 @@ C M() public async Task LValueFlowCapture_Assignment_ControlFlowInAssignedTarget(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - C M(C y) - { - C [|x|] = M2(); - (x ?? y) = y; - return x; - } + """ + class C + { + C M(C y) + { + C [|x|] = M2(); + (x ?? y) = y; + return x; + } - C M2() => null; -}", optionName); + C M2() => null; + } + """, optionName); } [Theory] @@ -1558,28 +1708,32 @@ C M(C y) public async Task LValueFlowCapture_Assignment_ControlFlowInAssignedValue_01(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - C M(C y, C z) - { - var [|x|] = M2(); - x = y ?? z; - return x; - } + """ + class C + { + C M(C y, C z) + { + var [|x|] = M2(); + x = y ?? z; + return x; + } - C M2() => null; -}", -$@"class C -{{ - C M(C y, C z) - {{ - {fix} = M2(); - C x = y ?? z; - return x; - }} + C M2() => null; + } + """, + $$""" + class C + { + C M(C y, C z) + { + {{fix}} = M2(); + C x = y ?? z; + return x; + } - C M2() => null; -}}", optionName); + C M2() => null; + } + """, optionName); } [Theory] @@ -1588,17 +1742,19 @@ C M(C y, C z) public async Task LValueFlowCapture_Assignment_ControlFlowInAssignedValue_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - C M(C y, C z) - { - C [|x|] = M2(); - x = y ?? (x ?? z); - return x; - } + """ + class C + { + C M(C y, C z) + { + C [|x|] = M2(); + x = y ?? (x ?? z); + return x; + } - C M2() => null; -}", optionName); + C M2() => null; + } + """, optionName); } [Theory] @@ -1607,17 +1763,19 @@ C M(C y, C z) public async Task LValueFlowCapture_DeconstructionAssignment_ControlFlowInAssignedTarget(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - C M(C y) - { - C [|x|] = M2(); - ((x ?? y), _) = (y, y); - return x; - } + """ + class C + { + C M(C y) + { + C [|x|] = M2(); + ((x ?? y), _) = (y, y); + return x; + } - C M2() => null; -}", optionName); + C M2() => null; + } + """, optionName); } [Theory] @@ -1626,29 +1784,33 @@ C M(C y) public async Task LValueFlowCapture_DeconstructionAssignment_ControlFlowInAssignedValue_01(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - C M(C y, C z) - { - var [|x|] = M2(); - (x, y) = (y ?? z, z); - return x; - } + """ + class C + { + C M(C y, C z) + { + var [|x|] = M2(); + (x, y) = (y ?? z, z); + return x; + } - C M2() => null; -}", -$@"class C -{{ - C M(C y, C z) - {{ - {fix} = M2(); - C x; - (x, y) = (y ?? z, z); - return x; - }} + C M2() => null; + } + """, + $$""" + class C + { + C M(C y, C z) + { + {{fix}} = M2(); + C x; + (x, y) = (y ?? z, z); + return x; + } - C M2() => null; -}}", optionName); + C M2() => null; + } + """, optionName); } [Theory] @@ -1657,98 +1819,112 @@ C M(C y, C z) public async Task LValueFlowCapture_DeconstructionAssignment_ControlFlowInAssignedValue_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - C M(C y, C z) - { - C [|x|] = M2(); - (x, y) = (y ?? x, z); - return x; - } + """ + class C + { + C M(C y, C z) + { + C [|x|] = M2(); + (x, y) = (y ?? x, z); + return x; + } - C M2() => null; -}", optionName); + C M2() => null; + } + """, optionName); } [Fact] public async Task Initialization_NonConstantValue_NoReferences_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|x|] = M2(); - } + """ + class C + { + void M() + { + int [|x|] = M2(); + } - int M2() => 0; -}", -@"class C -{ - void M() - { - _ = M2(); - } + int M2() => 0; + } + """, + """ + class C + { + void M() + { + _ = M2(); + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task Initialization_NonConstantValue_NoReferences_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|x|] = M2(); - } + """ + class C + { + void M() + { + int [|x|] = M2(); + } - int M2() => 0; -}", new TestParameters(options: PreferUnusedLocal)); + int M2() => 0; + } + """, new TestParameters(options: PreferUnusedLocal)); } [Fact] public async Task Initialization_NonConstantValue_NoReadReferences_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|x|] = M2(); - x = 0; - } + """ + class C + { + void M() + { + int [|x|] = M2(); + x = 0; + } - int M2() => 0; -}", -@"class C -{ - void M() - { - _ = M2(); - int x = 0; - } + int M2() => 0; + } + """, + """ + class C + { + void M() + { + _ = M2(); + int x = 0; + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task Initialization_NonConstantValue_NoReadReferences_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|x|] = M2(); - x = 0; - } + """ + class C + { + void M() + { + int [|x|] = M2(); + x = 0; + } - int M2() => 0; -}", new TestParameters(options: PreferUnusedLocal)); + int M2() => 0; + } + """, new TestParameters(options: PreferUnusedLocal)); } [Theory] @@ -1757,24 +1933,28 @@ void M() public async Task Initialization_ConstantValue_FirstField(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int [|x|] = 1, y = 2; - x = 2; - return x; - } -}", -@"class C -{ - int M() - { - int y = 2; - int x = 2; - return x; - } -}", optionName); + """ + class C + { + int M() + { + int [|x|] = 1, y = 2; + x = 2; + return x; + } + } + """, + """ + class C + { + int M() + { + int y = 2; + int x = 2; + return x; + } + } + """, optionName); } [Theory] @@ -1783,24 +1963,28 @@ int M() public async Task Initialization_ConstantValue_MiddleField(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int i = 0, [|x|] = 1, y = 2; - x = 2; - return x; - } -}", -@"class C -{ - int M() - { - int i = 0, y = 2; - int x = 2; - return x; - } -}", optionName); + """ + class C + { + int M() + { + int i = 0, [|x|] = 1, y = 2; + x = 2; + return x; + } + } + """, + """ + class C + { + int M() + { + int i = 0, y = 2; + int x = 2; + return x; + } + } + """, optionName); } [Theory] @@ -1809,196 +1993,224 @@ int M() public async Task Initialization_ConstantValue_LastField(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int i = 0, y = 2, [|x|] = 1; - x = 2; - return x; - } -}", -@"class C -{ - int M() - { - int i = 0, y = 2; - int x = 2; - return x; - } -}", optionName); + """ + class C + { + int M() + { + int i = 0, y = 2, [|x|] = 1; + x = 2; + return x; + } + } + """, + """ + class C + { + int M() + { + int i = 0, y = 2; + int x = 2; + return x; + } + } + """, optionName); } [Fact] public async Task Initialization_NonConstantValue_FirstField_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int [|x|] = M2(), y = 2; - x = 2; - return x; - } + """ + class C + { + int M() + { + int [|x|] = M2(), y = 2; + x = 2; + return x; + } - void M2() => 0; -}", -@"class C -{ - int M() - { - _ = M2(); - int y = 2; - int x = 2; - return x; - } + void M2() => 0; + } + """, + """ + class C + { + int M() + { + _ = M2(); + int y = 2; + int x = 2; + return x; + } - void M2() => 0; -}", options: PreferDiscard); + void M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task Initialization_NonConstantValue_FirstField_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int [|x|] = M2(), y = 2; - x = 2; - return x; - } + """ + class C + { + int M() + { + int [|x|] = M2(), y = 2; + x = 2; + return x; + } - void M2() => 0; -}", -@"class C -{ - int M() - { - int unused = M2(), y = 2; - int x = 2; - return x; - } + void M2() => 0; + } + """, + """ + class C + { + int M() + { + int unused = M2(), y = 2; + int x = 2; + return x; + } - void M2() => 0; -}", options: PreferUnusedLocal); + void M2() => 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task Initialization_NonConstantValue_MiddleField_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int i = 0, [|x|] = M2(), y = 2; - x = 2; - return x; - } + """ + class C + { + int M() + { + int i = 0, [|x|] = M2(), y = 2; + x = 2; + return x; + } - void M2() => 0; -}", -@"class C -{ - int M() - { - int i = 0; - _ = M2(); - int y = 2; - int x = 2; - return x; - } + void M2() => 0; + } + """, + """ + class C + { + int M() + { + int i = 0; + _ = M2(); + int y = 2; + int x = 2; + return x; + } - void M2() => 0; -}", options: PreferDiscard); + void M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task Initialization_NonConstantValue_MiddleField_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int i = 0, [|x|] = M2(), y = 2; - x = 2; - return x; - } + """ + class C + { + int M() + { + int i = 0, [|x|] = M2(), y = 2; + x = 2; + return x; + } - void M2() => 0; -}", -@"class C -{ - int M() - { - int i = 0, unused = M2(), y = 2; - int x = 2; - return x; - } + void M2() => 0; + } + """, + """ + class C + { + int M() + { + int i = 0, unused = M2(), y = 2; + int x = 2; + return x; + } - void M2() => 0; -}", options: PreferUnusedLocal); + void M2() => 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task Initialization_NonConstantValue_LastField_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int i = 0, y = 2, [|x|] = M2(); - x = 2; - return x; - } + """ + class C + { + int M() + { + int i = 0, y = 2, [|x|] = M2(); + x = 2; + return x; + } - void M2() => 0; -}", -@"class C -{ - int M() - { - int i = 0, y = 2; - _ = M2(); - int x = 2; - return x; - } + void M2() => 0; + } + """, + """ + class C + { + int M() + { + int i = 0, y = 2; + _ = M2(); + int x = 2; + return x; + } - void M2() => 0; -}", options: PreferDiscard); + void M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task Initialization_NonConstantValue_LastField_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int i = 0, y = 2, [|x|] = M2(); - x = 2; - return x; - } + """ + class C + { + int M() + { + int i = 0, y = 2, [|x|] = M2(); + x = 2; + return x; + } - void M2() => 0; -}", -@"class C -{ - int M() - { - int i = 0, y = 2, unused = M2(); - int x = 2; - return x; - } + void M2() => 0; + } + """, + """ + class C + { + int M() + { + int i = 0, y = 2, unused = M2(); + int x = 2; + return x; + } - void M2() => 0; -}", options: PreferUnusedLocal); + void M2() => 0; + } + """, options: PreferUnusedLocal); } [Theory] @@ -2007,29 +2219,33 @@ int M() public async Task Assignment_BeforeUseAsOutArgument(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x; - [|x|] = 1; - M2(out x); - return x; - } - - void M2(out int x) => x = 0; -}", -@"class C -{ - int M() - { - int x; - M2(out x); - return x; - } + """ + class C + { + int M() + { + int x; + [|x|] = 1; + M2(out x); + return x; + } - void M2(out int x) => x = 0; -}", optionName); + void M2(out int x) => x = 0; + } + """, + """ + class C + { + int M() + { + int x; + M2(out x); + return x; + } + + void M2(out int x) => x = 0; + } + """, optionName); } [Theory] @@ -2038,18 +2254,20 @@ int M() public async Task NonRedundantAssignment_BeforeUseAsRefArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x; - [|x|] = 1; - M2(ref x); - return x; - } + """ + class C + { + int M() + { + int x; + [|x|] = 1; + M2(ref x); + return x; + } - void M2(ref int x) => x = 0; -}", optionName); + void M2(ref int x) => x = 0; + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/40717")] @@ -2058,26 +2276,28 @@ int M() public async Task NonRedundantAssignment_AfterUseAsRefArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - static int Example() - { - int value = 1; + class C + { + static int Example() + { + int value = 1; - Span valueSpan = M(ref value); + Span valueSpan = M(ref value); - [|value = 2;|] + [|value = 2;|] - return valueSpan[0]; - } + return valueSpan[0]; + } - static Span M(ref int value) - { - return default; - } -}", optionName); + static Span M(ref int value) + { + return default; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/40483")] @@ -2086,29 +2306,31 @@ static Span M(ref int value) public async Task NonRedundantAssignment_AfterUseAsRefArgument_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class P -{ - public ref bool f(ref bool z, ref bool q) - { - z = ref q; - return ref z; - } -} + class P + { + public ref bool f(ref bool z, ref bool q) + { + z = ref q; + return ref z; + } + } -class Q -{ - static void F() - { - bool a = true; - bool b = false; - ref var r = ref new P().f(ref a, ref b); - [|b = true|]; + class Q + { + static void F() + { + bool a = true; + bool b = false; + ref var r = ref new P().f(ref a, ref b); + [|b = true|]; - Console.WriteLine(r); - } -}", optionName); + Console.WriteLine(r); + } + } + """, optionName); } [Theory] @@ -2117,142 +2339,162 @@ static void F() public async Task NonRedundantAssignment_BeforeUseAsInArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x; - [|x|] = 1; - M2(in x); - return x; - } + """ + class C + { + int M() + { + int x; + [|x|] = 1; + M2(in x); + return x; + } - void M2(in int x) { } -}", optionName); + void M2(in int x) { } + } + """, optionName); } [Fact] public async Task OutArgument_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x; - M2(out [|x|]); - x = 1; - return x; - } + """ + class C + { + int M() + { + int x; + M2(out [|x|]); + x = 1; + return x; + } - void M2(out int x) => x = 0; -}", -@"class C -{ - int M() - { - int x; - M2(out _); - x = 1; - return x; - } + void M2(out int x) => x = 0; + } + """, + """ + class C + { + int M() + { + int x; + M2(out _); + x = 1; + return x; + } - void M2(out int x) => x = 0; -}", options: PreferDiscard); + void M2(out int x) => x = 0; + } + """, options: PreferDiscard); } [Fact] public async Task OutArgument_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x; - M2(out [|x|]); - x = 1; - return x; - } + """ + class C + { + int M() + { + int x; + M2(out [|x|]); + x = 1; + return x; + } - void M2(out int x) => x = 0; -}", -@"class C -{ - int M() - { - int x; - int unused; - M2(out unused); - x = 1; - return x; - } + void M2(out int x) => x = 0; + } + """, + """ + class C + { + int M() + { + int x; + int unused; + M2(out unused); + x = 1; + return x; + } - void M2(out int x) => x = 0; -}", options: PreferUnusedLocal); + void M2(out int x) => x = 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task OutVarArgument_ExpressionBody_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() => M2(out var [|x|]); - void M2(out int x) => x = 0; -}", -@"class C -{ - void M() => M2(out _); - void M2(out int x) => x = 0; -}", options: PreferDiscard); + """ + class C + { + void M() => M2(out var [|x|]); + void M2(out int x) => x = 0; + } + """, + """ + class C + { + void M() => M2(out _); + void M2(out int x) => x = 0; + } + """, options: PreferDiscard); } [Fact] public async Task OutArgument_NoReads_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - int x; - M2(out [|x|]); + """ + class C + { + void M() + { + int x; + M2(out [|x|]); - // Unrelated, unused local should not be removed. - int unused; - } + // Unrelated, unused local should not be removed. + int unused; + } - void M2(out int x) => x = 0; -}", -@"class C -{ - void M() - { - M2(out _); + void M2(out int x) => x = 0; + } + """, + """ + class C + { + void M() + { + M2(out _); - // Unrelated, unused local should not be removed. - int unused; - } + // Unrelated, unused local should not be removed. + int unused; + } - void M2(out int x) => x = 0; -}", options: PreferDiscard); + void M2(out int x) => x = 0; + } + """, options: PreferDiscard); } [Fact] public async Task OutArgument_NoReads_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int x; - M2(out [|x|]); - } + """ + class C + { + void M() + { + int x; + M2(out [|x|]); + } - void M2(out int x) => x = 0; -}", options: PreferUnusedLocal); + void M2(out int x) => x = 0; + } + """, options: PreferUnusedLocal); } [Theory] @@ -2261,28 +2503,32 @@ void M() public async Task OutDeclarationExpressionArgument(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - M2(out var [|x|]); - x = 1; - return x; - } + """ + class C + { + int M() + { + M2(out var [|x|]); + x = 1; + return x; + } - void M2(out int x) => x = 0; -}", -$@"class C -{{ - int M() - {{ - M2(out {fix}); - int x = 1; - return x; - }} + void M2(out int x) => x = 0; + } + """, + $$""" + class C + { + int M() + { + M2(out {{fix}}); + int x = 1; + return x; + } - void M2(out int x) => x = 0; -}}", optionName); + void M2(out int x) => x = 0; + } + """, optionName); } [Theory] @@ -2291,17 +2537,19 @@ int M() public async Task NonRedundantRefArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M(int x) - { - M2(ref [|x|]); - x = 1; - return x; - } + """ + class C + { + int M(int x) + { + M2(ref [|x|]); + x = 1; + return x; + } - void M2(ref int x) => x = 0; -}", optionName); + void M2(ref int x) => x = 0; + } + """, optionName); } [Theory] @@ -2310,17 +2558,19 @@ int M(int x) public async Task NonRedundantInArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M(int x) - { - M2(in [|x|]); - x = 1; - return x; - } + """ + class C + { + int M(int x) + { + M2(in [|x|]); + x = 1; + return x; + } - void M2(in int x) { } -}", optionName); + void M2(in int x) { } + } + """, optionName); } [Theory] @@ -2329,77 +2579,89 @@ void M2(in int x) { } public async Task DeconstructionDeclarationExpression(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - var ([|x|], y) = (1, 1); - x = 1; - return x; - } -}", -$@"class C -{{ - int M() - {{ - var ({fix}, y) = (1, 1); - int x = 1; - return x; - }} -}}", optionName); + """ + class C + { + int M() + { + var ([|x|], y) = (1, 1); + x = 1; + return x; + } + } + """, + $$""" + class C + { + int M() + { + var ({{fix}}, y) = (1, 1); + int x = 1; + return x; + } + } + """, optionName); } [Fact] public async Task DeconstructionAssignment_01_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x, y; - ([|x|], y) = (1, 1); - x = 1; - return x; - } -}", -@"class C -{ - int M() - { - int x, y; - (_, y) = (1, 1); - x = 1; - return x; - } -}", options: PreferDiscard); + """ + class C + { + int M() + { + int x, y; + ([|x|], y) = (1, 1); + x = 1; + return x; + } + } + """, + """ + class C + { + int M() + { + int x, y; + (_, y) = (1, 1); + x = 1; + return x; + } + } + """, options: PreferDiscard); } [Fact] public async Task DeconstructionAssignment_01_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int x, y; - ([|x|], y) = (1, 1); - x = 1; - return x; - } -}", -@"class C -{ - int M() - { - int x, y; - int unused; - (unused, y) = (1, 1); - x = 1; - return x; - } -}", options: PreferUnusedLocal); + """ + class C + { + int M() + { + int x, y; + ([|x|], y) = (1, 1); + x = 1; + return x; + } + } + """, + """ + class C + { + int M() + { + int x, y; + int unused; + (unused, y) = (1, 1); + x = 1; + return x; + } + } + """, options: PreferUnusedLocal); } [Theory] @@ -2408,15 +2670,17 @@ int M() public async Task DeconstructionAssignment_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M() - { - int [|x|] = 0, y = 0; - (x, y) = (x, y); - return x; - } -}", optionName); + """ + class C + { + int M() + { + int [|x|] = 0, y = 0; + (x, y) = (x, y); + return x; + } + } + """, optionName); } [Theory] @@ -2425,84 +2689,96 @@ int M() public async Task TupleExpressionWithDeclarationExpressions(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - (var [|x|], var y) = (1, 1); - x = 1; - return x; - } -}", -$@"class C -{{ - int M() - {{ - ({fix}, var y) = (1, 1); - int x = 1; - return x; - }} -}}", optionName); - } - - [Fact] - public async Task DeclarationPatternInSwitchCase_WithOnlyWriteReference_PreferDiscard() + """ + class C + { + int M() + { + (var [|x|], var y) = (1, 1); + x = 1; + return x; + } + } + """, + $$""" + class C + { + int M() + { + ({{fix}}, var y) = (1, 1); + int x = 1; + return x; + } + } + """, optionName); + } + + [Fact] + public async Task DeclarationPatternInSwitchCase_WithOnlyWriteReference_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - switch (p) - { - case int [|x|]: - x = 1; - break; - }; - } -}", -@"class C -{ - void M(object p) - { - switch (p) - { - case int _: - int x = 1; - break; - }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + void M(object p) + { + switch (p) + { + case int [|x|]: + x = 1; + break; + }; + } + } + """, + """ + class C + { + void M(object p) + { + switch (p) + { + case int _: + int x = 1; + break; + }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact] public async Task DeclarationPatternInSwitchCase_WithOnlyWriteReference_PreferDiscard_CSharp9() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - switch (p) - { - case int [|x|]: - x = 1; - break; - }; - } -}", -@"class C -{ - void M(object p) - { - switch (p) - { - case int: - int x = 1; - break; - }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp9)); + """ + class C + { + void M(object p) + { + switch (p) + { + case int [|x|]: + x = 1; + break; + }; + } + } + """, + """ + class C + { + void M(object p) + { + switch (p) + { + case int: + int x = 1; + break; + }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp9)); } [Theory] @@ -2511,18 +2787,20 @@ public async Task DeclarationPatternInSwitchCase_WithOnlyWriteReference_PreferUn [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - switch (p) - { - case int [|x|]: - x = 1; - break; - }; - } -}", new TestParameters(options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion))); + """ + class C + { + void M(object p) + { + switch (p) + { + case int [|x|]: + x = 1; + break; + }; + } + } + """, new TestParameters(options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion))); } [Theory] @@ -2531,22 +2809,25 @@ public async Task DeclarationPatternInSwitchCase_WithOnlyWriteReference_TypePatt [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - void M(object p) - { - switch (p) - { - case int {|IDE0059:x|}: - {|IDE0059:x|} = 1; - break; - }; - } -}"; + """ + class C + { + void M(object p) + { + switch (p) + { + case int {|IDE0059:x|}: + {|IDE0059:x|} = 1; + break; + }; + } + } + """; var (fixedSource, iterations) = testBehaviors switch { CodeFixTestBehaviors.None => -(@"class C +(""" +class C { void M(object p) { @@ -2556,9 +2837,11 @@ void M(object p) break; }; } -}", iterations: 2), +} +""", iterations: 2), CodeFixTestBehaviors.FixOne => -(@"class C +(""" +class C { void M(object p) { @@ -2569,7 +2852,8 @@ void M(object p) break; }; } -}", iterations: 1), +} +""", iterations: 1), _ => throw ExceptionUtilities.Unreachable(), }; @@ -2592,81 +2876,93 @@ void M(object p) public async Task DeclarationPatternInIsPattern_WithNoReference_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - if (p is C [|x|]) - { - } - } -}", -@"class C -{ - void M(object p) - { - if (p is C) - { - } - } -}", options: PreferDiscard); + """ + class C + { + void M(object p) + { + if (p is C [|x|]) + { + } + } + } + """, + """ + class C + { + void M(object p) + { + if (p is C) + { + } + } + } + """, options: PreferDiscard); } [Fact] public async Task DeclarationPatternInIsPattern_WithNoReference_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - if (p is C [|x|]) - { - } - } -}", options: PreferUnusedLocal); + """ + class C + { + void M(object p) + { + if (p is C [|x|]) + { + } + } + } + """, options: PreferUnusedLocal); } [Fact] public async Task DeclarationPatternInIsPattern_WithOnlyWriteReference_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - if (p is C [|x|]) - { - x = null; - } - } -}", -@"class C -{ - void M(object p) - { - if (p is C) - { - C x = null; - } - } -}", options: PreferDiscard); + """ + class C + { + void M(object p) + { + if (p is C [|x|]) + { + x = null; + } + } + } + """, + """ + class C + { + void M(object p) + { + if (p is C) + { + C x = null; + } + } + } + """, options: PreferDiscard); } [Fact] public async Task DeclarationPatternInIsPattern_WithOnlyWriteReference_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - if (p is C [|x|]) - { - x = null; - } - } -}", options: PreferUnusedLocal); + """ + class C + { + void M(object p) + { + if (p is C [|x|]) + { + x = null; + } + } + } + """, options: PreferUnusedLocal); } [Theory] @@ -2675,48 +2971,56 @@ void M(object p) public async Task DeclarationPatternInIsPattern_WithReadAndWriteReference(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - if (p is C [|x|]) - { - x = null; - p = x; - } - } -}", -$@"class C -{{ - void M(object p) - {{ - if (p is {fix}) - {{ - C x = null; - p = x; - }} - }} -}}", optionName: optionName); + """ + class C + { + void M(object p) + { + if (p is C [|x|]) + { + x = null; + p = x; + } + } + } + """, + $$""" + class C + { + void M(object p) + { + if (p is {{fix}}) + { + C x = null; + p = x; + } + } + } + """, optionName: optionName); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] public async Task DeclarationPatternInRecursivePattern_WithNoReference_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => false }; - } -}", -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int _, int x2) => false }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => false }; + } + } + """, + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int _, int x2) => false }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] @@ -2725,13 +3029,15 @@ public async Task DeclarationPatternInRecursivePattern_WithNoReference_PreferUnu [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => false }; - } -}", options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion)); + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => false }; + } + } + """, options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] @@ -2740,35 +3046,41 @@ public async Task DeclarationPatternInRecursivePattern_WithNoReference_TypePatte [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - bool M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int {|IDE0059:x1|}, int {|IDE0059:x2|}) => false }; - return isZero; - } -}"; + """ + class C + { + bool M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int {|IDE0059:x1|}, int {|IDE0059:x2|}) => false }; + return isZero; + } + } + """; var batchFixedSource = -@"class C -{ - bool M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int, int) => false }; - return isZero; - } -}"; + """ + class C + { + bool M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int, int) => false }; + return isZero; + } + } + """; var fixedSource = testBehaviors switch { CodeFixTestBehaviors.None => batchFixedSource, CodeFixTestBehaviors.FixOne => - @"class C -{ - bool M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int, int {|IDE0059:x2|}) => false }; - return isZero; - } -}", + """ + class C + { + bool M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int, int {|IDE0059:x2|}) => false }; + return isZero; + } + } + """, _ => throw ExceptionUtilities.Unreachable() }; @@ -2790,33 +3102,37 @@ bool M(object p1, object p2) public async Task DeclarationPatternInRecursivePattern_WithOnlyWriteReference_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(out x1) }; - } + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(out x1) }; + } - bool M2(out int x) - { - x = 0; - return false; - } -}", -@"class C -{ - void M(object p1, object p2) - { - int x1; - var isZero = (p1, p2) switch { (0, 0) => true, (int _, int x2) => M2(out x1) }; - } + bool M2(out int x) + { + x = 0; + return false; + } + } + """, + """ + class C + { + void M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int _, int x2) => M2(out x1) }; + } - bool M2(out int x) - { - x = 0; - return false; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + bool M2(out int x) + { + x = 0; + return false; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] @@ -2825,19 +3141,21 @@ public async Task DeclarationPatternInRecursivePattern_WithOnlyWriteReference_Pr [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(out x1) }; - } + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(out x1) }; + } - bool M2(out int x) - { - x = 0; - return false; - } -}", options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion)); + bool M2(out int x) + { + x = 0; + return false; + } + } + """, options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] @@ -2846,54 +3164,60 @@ public async Task DeclarationPatternInRecursivePattern_WithOnlyWriteReference_Ty [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - bool M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int {|IDE0059:x1|}, int {|IDE0059:x2|}) => M2(out {|IDE0059:x1|}) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int {|IDE0059:x1|}, int {|IDE0059:x2|}) => M2(out {|IDE0059:x1|}) }; + return isZero; + } - bool M2(out int x) - { - x = 0; - return false; - } -}"; + bool M2(out int x) + { + x = 0; + return false; + } + } + """; var batchFixedSource = -@"class C -{ - bool M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int, int) => M2(out _) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int, int) => M2(out _) }; + return isZero; + } - bool M2(out int x) - { - x = 0; - return false; - } -}"; + bool M2(out int x) + { + x = 0; + return false; + } + } + """; var fixedSource = testBehaviors switch { CodeFixTestBehaviors.None => batchFixedSource, CodeFixTestBehaviors.FixOne => -@"class C -{ - bool M(object p1, object p2) - { - int x1; - var isZero = (p1, p2) switch { (0, 0) => true, (int, int {|IDE0059:x2|}) => M2(out {|IDE0059:x1|}) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int, int {|IDE0059:x2|}) => M2(out {|IDE0059:x1|}) }; + return isZero; + } - bool M2(out int x) - { - x = 0; - return false; - } -}", + bool M2(out int x) + { + x = 0; + return false; + } + } + """, _ => throw ExceptionUtilities.Unreachable(), }; @@ -2917,31 +3241,35 @@ bool M2(out int x) public async Task DeclarationPatternInRecursivePattern_WithReadAndWriteReference(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(x1 = 0) && M2(x1) }; - } + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(x1 = 0) && M2(x1) }; + } - bool M2(int x) - { - return false; - } -}", -$@"class C -{{ - void M(object p1, object p2) - {{ - int x1; - var isZero = (p1, p2) switch {{ (0, 0) => true, (int {fix}, int x2) => M2(x1 = 0) && M2(x1) }}; - }} - - bool M2(int x) - {{ - return false; - }} -}}", optionName: optionName, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + bool M2(int x) + { + return false; + } + } + """, + $$""" + class C + { + void M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int {{fix}}, int x2) => M2(x1 = 0) && M2(x1) }; + } + + bool M2(int x) + { + return false; + } + } + """, optionName: optionName, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] @@ -2950,31 +3278,35 @@ bool M2(int x) public async Task DeclarationPatternInRecursivePattern_WithReadAndWriteReference_TypePatternxxxxxxxxxxxxxxxxxxxxxx(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(x1 = 0) && M2(x1) }; - } + """ + class C + { + void M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int [|x1|], int x2) => M2(x1 = 0) && M2(x1) }; + } - bool M2(int x) - { - return false; - } -}", -$@"class C -{{ - void M(object p1, object p2) - {{ - int x1; - var isZero = (p1, p2) switch {{ (0, 0) => true, (int{fix}, int x2) => M2(x1 = 0) && M2(x1) }}; - }} - - bool M2(int x) - {{ - return false; - }} -}}", optionName: optionName, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp9)); + bool M2(int x) + { + return false; + } + } + """, + $$""" + class C + { + void M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int{{fix}}, int x2) => M2(x1 = 0) && M2(x1) }; + } + + bool M2(int x) + { + return false; + } + } + """, optionName: optionName, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp9)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32271")] @@ -2984,67 +3316,75 @@ public async Task DeclarationPatternInRecursivePattern_WithReadAndWriteReference [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - bool M(object p1, object p2) - { - var isZero = (p1, p2) switch { (0, 0) => true, (int {|IDE0059:x1|}, int {|#0:x2|}) => M2(x1 = 0) && M2(x1) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + var isZero = (p1, p2) switch { (0, 0) => true, (int {|IDE0059:x1|}, int {|#0:x2|}) => M2(x1 = 0) && M2(x1) }; + return isZero; + } - bool M2(int {|IDE0060:x|}) - { - return false; - } -}"; + bool M2(int {|IDE0060:x|}) + { + return false; + } + } + """; var fixedSource = ((UnusedValuePreference)option, testBehaviors) switch { (UnusedValuePreference.DiscardVariable, CodeFixTestBehaviors.None) => -@"class C -{ - bool M(object p1, object p2) - { - int x1; - var isZero = (p1, p2) switch { (0, 0) => true, (int, int) => M2(x1 = 0) && M2(x1) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int, int) => M2(x1 = 0) && M2(x1) }; + return isZero; + } - bool M2(int {|IDE0060:x|}) - { - return false; - } -}", + bool M2(int {|IDE0060:x|}) + { + return false; + } + } + """, (UnusedValuePreference.DiscardVariable, CodeFixTestBehaviors.FixOne | CodeFixTestBehaviors.SkipFixAllCheck) => -@"class C -{ - bool M(object p1, object p2) - { - int x1; - var isZero = (p1, p2) switch { (0, 0) => true, (int, int {|IDE0059:x2|}) => M2(x1 = 0) && M2(x1) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int, int {|IDE0059:x2|}) => M2(x1 = 0) && M2(x1) }; + return isZero; + } - bool M2(int {|IDE0060:x|}) - { - return false; - } -}", + bool M2(int {|IDE0060:x|}) + { + return false; + } + } + """, (UnusedValuePreference.UnusedLocalVariable, _) => -@"class C -{ - bool M(object p1, object p2) - { - int x1; - var isZero = (p1, p2) switch { (0, 0) => true, (int unused, int x2) => M2(x1 = 0) && M2(x1) }; - return isZero; - } + """ + class C + { + bool M(object p1, object p2) + { + int x1; + var isZero = (p1, p2) switch { (0, 0) => true, (int unused, int x2) => M2(x1 = 0) && M2(x1) }; + return isZero; + } - bool M2(int {|IDE0060:x|}) - { - return false; - } -}", + bool M2(int {|IDE0060:x|}) + { + return false; + } + } + """, _ => throw ExceptionUtilities.Unreachable(), }; @@ -3076,21 +3416,23 @@ bool M2(int {|IDE0060:x|}) public async Task UseInLambda_WithInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - var x = p; - }; + class C + { + void M(object p) + { + Action lambda = () => + { + var x = p; + }; - [|p|] = null; - lambda(); - } -}", optionName); + [|p|] = null; + lambda(); + } + } + """, optionName); } [Theory] @@ -3099,21 +3441,23 @@ void M(object p) public async Task UseInLocalFunction_WithInvocation_DefinedAtStart(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - var x = p; - } + class C + { + void M(object p) + { + void LocalFunction() + { + var x = p; + } - [|p|] = null; - LocalFunction(); - } -}", optionName); + [|p|] = null; + LocalFunction(); + } + } + """, optionName); } [Theory] @@ -3122,21 +3466,23 @@ void LocalFunction() public async Task UseInLocalFunction_WithInvocation_DefinedAtEnd(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - LocalFunction(); + class C + { + void M(object p) + { + [|p|] = null; + LocalFunction(); - void LocalFunction() - { - var x = p; - } - } -}", optionName); + void LocalFunction() + { + var x = p; + } + } + } + """, optionName); } [Theory] @@ -3145,31 +3491,35 @@ void LocalFunction() public async Task UseInLambda_WithoutInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - Action lambda = () => - { - var x = p; - }; - } -}", -@"using System; + class C + { + void M(object p) + { + [|p|] = null; + Action lambda = () => + { + var x = p; + }; + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - var x = p; - }; - } -}", optionName); + class C + { + void M(object p) + { + Action lambda = () => + { + var x = p; + }; + } + } + """, optionName); } [Theory] @@ -3178,31 +3528,35 @@ void M(object p) public async Task UseInLocalFunction_WithoutInvocation_DefinedAtStart(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - var x = p; - } - [|p|] = null; - } -}", -@"using System; + class C + { + void M(object p) + { + void LocalFunction() + { + var x = p; + } + [|p|] = null; + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - var x = p; - } - } -}", optionName); + class C + { + void M(object p) + { + void LocalFunction() + { + var x = p; + } + } + } + """, optionName); } [Theory] @@ -3211,31 +3565,35 @@ void LocalFunction() public async Task UseInLocalFunction_WithoutInvocation_DefinedAtEnd(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - void LocalFunction() - { - var x = p; - } - } -}", -@"using System; + class C + { + void M(object p) + { + [|p|] = null; + void LocalFunction() + { + var x = p; + } + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - var x = p; - } - } -}", optionName); + class C + { + void M(object p) + { + void LocalFunction() + { + var x = p; + } + } + } + """, optionName); } [Theory] @@ -3244,31 +3602,35 @@ void LocalFunction() public async Task NotUseInLambda_WithInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - }; - [|p|] = null; - lambda(); - } -}", -@"using System; + class C + { + void M(object p) + { + Action lambda = () => + { + }; + [|p|] = null; + lambda(); + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - }; - lambda(); - } -}", optionName); + class C + { + void M(object p) + { + Action lambda = () => + { + }; + lambda(); + } + } + """, optionName); } [Theory] @@ -3277,31 +3639,35 @@ void M(object p) public async Task NotUseInLocalFunction_WithInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - LocalFunction(); - void LocalFunction() - { - } - } -}", -@"using System; + class C + { + void M(object p) + { + [|p|] = null; + LocalFunction(); + void LocalFunction() + { + } + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - LocalFunction(); - void LocalFunction() - { - } - } -}", optionName); + class C + { + void M(object p) + { + LocalFunction(); + void LocalFunction() + { + } + } + } + """, optionName); } [Theory] @@ -3310,29 +3676,33 @@ void LocalFunction() public async Task NotUseInLambda_WithoutInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - Action lambda = () => - { - }; - } -}", -@"using System; + class C + { + void M(object p) + { + [|p|] = null; + Action lambda = () => + { + }; + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - }; - } -}", optionName); + class C + { + void M(object p) + { + Action lambda = () => + { + }; + } + } + """, optionName); } [Theory] @@ -3341,29 +3711,33 @@ void M(object p) public async Task NotUseInLocalFunction_WithoutInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - void LocalFunction() - { - } - } -}", -@"using System; + class C + { + void M(object p) + { + [|p|] = null; + void LocalFunction() + { + } + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - } - } -}", optionName); + class C + { + void M(object p) + { + void LocalFunction() + { + } + } + } + """, optionName); } [Theory] @@ -3372,31 +3746,35 @@ void LocalFunction() public async Task RedundantWriteInLambda_WithInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - [|p|] = null; - }; - lambda(); - } -}", -@"using System; + class C + { + void M(object p) + { + Action lambda = () => + { + [|p|] = null; + }; + lambda(); + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - }; - lambda(); - } -}", optionName); + class C + { + void M(object p) + { + Action lambda = () => + { + }; + lambda(); + } + } + """, optionName); } [Theory] @@ -3405,31 +3783,35 @@ void M(object p) public async Task RedundantWriteInLocalFunction_WithInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - LocalFunction(); - void LocalFunction() - { - [|p|] = null; - } - } -}", -@"using System; + class C + { + void M(object p) + { + LocalFunction(); + void LocalFunction() + { + [|p|] = null; + } + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - LocalFunction(); - void LocalFunction() - { - } - } -}", optionName); + class C + { + void M(object p) + { + LocalFunction(); + void LocalFunction() + { + } + } + } + """, optionName); } [Theory] @@ -3438,20 +3820,22 @@ void LocalFunction() public async Task WriteThenReadInLambda_WithInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - [|p|] = null; - var x = p; - }; - lambda(); - } -}", optionName); + class C + { + void M(object p) + { + Action lambda = () => + { + [|p|] = null; + var x = p; + }; + lambda(); + } + } + """, optionName); } [Theory] @@ -3460,20 +3844,22 @@ void M(object p) public async Task WriteThenReadInLocalFunction_WithInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - LocalFunction(); - void LocalFunction() - { - [|p|] = null; - var x = p; - } - } -}", optionName); + class C + { + void M(object p) + { + LocalFunction(); + void LocalFunction() + { + [|p|] = null; + var x = p; + } + } + } + """, optionName); } [Theory] @@ -3482,18 +3868,20 @@ void LocalFunction() public async Task RedundantWriteInLambda_WithoutInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - [|p|] = null; - }; - } -}", optionName); + class C + { + void M(object p) + { + Action lambda = () => + { + [|p|] = null; + }; + } + } + """, optionName); } [Theory] @@ -3502,18 +3890,20 @@ void M(object p) public async Task RedundantWriteInLocalFunction_WithoutInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - [|p|] = null; - } - } -}", optionName); + class C + { + void M(object p) + { + void LocalFunction() + { + [|p|] = null; + } + } + } + """, optionName); } [Theory] @@ -3522,28 +3912,30 @@ void LocalFunction() public async Task UseInLambda_Nested(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action outerLambda = () => - { - Action innerLambda = () => - { - var x = p; - }; + class C + { + void M(object p) + { + Action outerLambda = () => + { + Action innerLambda = () => + { + var x = p; + }; - innerLambda(); - }); + innerLambda(); + }); - [|p|] = null; - outerLambda(); - } + [|p|] = null; + outerLambda(); + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -3552,28 +3944,30 @@ void M(object p) public async Task UseInLocalFunction_NestedLocalFunction(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - OuterLocalFunction(); + class C + { + void M(object p) + { + [|p|] = null; + OuterLocalFunction(); - void OuterLocalFunction() - { - InnerLocalFunction(); + void OuterLocalFunction() + { + InnerLocalFunction(); - void InnerLocalFunction() - { - var x = p; - } - }); - } + void InnerLocalFunction() + { + var x = p; + } + }); + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -3582,23 +3976,25 @@ void InnerLocalFunction() public async Task UseInLambda_NestedLocalFunction(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, Action outerDelegate) - { - [|p|] = null; - outerDelegate(() => - { - InnerLocalFunction(); - void InnerLocalFunction() - { - var x = p; - } - }); - } -}", optionName); + class C + { + void M(object p, Action outerDelegate) + { + [|p|] = null; + outerDelegate(() => + { + InnerLocalFunction(); + void InnerLocalFunction() + { + var x = p; + } + }); + } + } + """, optionName); } [Theory] @@ -3607,24 +4003,26 @@ void InnerLocalFunction() public async Task UseInLocalFunction_NestedLambda(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, Action myDelegate) - { - [|p|] = null; - OuterLocalFunction(); + class C + { + void M(object p, Action myDelegate) + { + [|p|] = null; + OuterLocalFunction(); - void OuterLocalFunction() - { - myDelegate(() => - { - var x = p; - }); - } - } -}", optionName); + void OuterLocalFunction() + { + myDelegate(() => + { + var x = p; + }); + } + } + } + """, optionName); } [Theory] @@ -3633,25 +4031,27 @@ void OuterLocalFunction() public async Task UseInNestedLambda_InvokedInOuterFunction(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, Action myDelegate) - { - [|p|] = null; - OuterLocalFunction(); - myDelegate(); + class C + { + void M(object p, Action myDelegate) + { + [|p|] = null; + OuterLocalFunction(); + myDelegate(); - void OuterLocalFunction() - { - myDelegate = () => - { - var x = p; - }; - } - } -}", optionName); + void OuterLocalFunction() + { + myDelegate = () => + { + var x = p; + }; + } + } + } + """, optionName); } [Theory] @@ -3660,26 +4060,28 @@ void OuterLocalFunction() public async Task UseInNestedLocalFunction_InvokedInOuterFunction(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, Action myDelegate) - { - [|p|] = null; - OuterLocalFunction(); - myDelegate(); + class C + { + void M(object p, Action myDelegate) + { + [|p|] = null; + OuterLocalFunction(); + myDelegate(); - void OuterLocalFunction() - { - myDelegate = NestedLocalFunction; - void NestedLocalFunction() - { - var x = p; - } - } - } -}", optionName); + void OuterLocalFunction() + { + myDelegate = NestedLocalFunction; + void NestedLocalFunction() + { + var x = p; + } + } + } + } + """, optionName); } [Theory] @@ -3688,16 +4090,18 @@ void NestedLocalFunction() public async Task UseInLambda_ArgumentToLambda(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, Action myDelegate) - { - [|p|] = null; - myDelegate(p); - } -}", optionName); + class C + { + void M(object p, Action myDelegate) + { + [|p|] = null; + myDelegate(p); + } + } + """, optionName); } [Theory] @@ -3706,16 +4110,18 @@ void M(object p, Action myDelegate) public async Task UseInLambda_ArgumentToLambda_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action M(object p, Action myDelegate) - { - [|p|] = null; - return d => { myDelegate(0); }; - } -}", optionName); + class C + { + Action M(object p, Action myDelegate) + { + [|p|] = null; + return d => { myDelegate(0); }; + } + } + """, optionName); } [Theory] @@ -3724,21 +4130,23 @@ Action M(object p, Action myDelegate) public async Task UseInLambda_PassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - M2(() => - { - var x = p; - }); - } + class C + { + void M(object p) + { + [|p|] = null; + M2(() => + { + var x = p; + }); + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -3747,29 +4155,31 @@ void M(object p) public async Task UseInLambda_PassedAsArgument_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - public C(bool flag) - { - Flag = flag; - } + class C + { + public C(bool flag) + { + Flag = flag; + } - public bool Flag { get; } - public static bool M() - { - bool flag = true; - var c = Create(() => flag); + public bool Flag { get; } + public static bool M() + { + bool flag = true; + var c = Create(() => flag); - M2(c); - [|flag|] = false; - return M2(c); - } + M2(c); + [|flag|] = false; + return M2(c); + } - private static C Create(Func isFlagTrue) { return new C(isFlagTrue()); } - private static bool M2(C c) => c.Flag; -}", optionName); + private static C Create(Func isFlagTrue) { return new C(isFlagTrue()); } + private static bool M2(C c) => c.Flag; + } + """, optionName); } [Theory] @@ -3778,23 +4188,25 @@ public static bool M() public async Task UseInLocalFunction_PassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - M2(LocalFunction); + class C + { + void M(object p) + { + [|p|] = null; + M2(LocalFunction); - void LocalFunction() - { - var x = p; - } - } + void LocalFunction() + { + var x = p; + } + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -3803,23 +4215,25 @@ void LocalFunction() public async Task UseInLambda_PassedAsArgument_CustomDelegate(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -public delegate void MyAction(); + public delegate void MyAction(); -class C -{ - void M(object p) - { - [|p|] = null; - M2(() => - { - var x = p; - }); - } + class C + { + void M(object p) + { + [|p|] = null; + M2(() => + { + var x = p; + }); + } - void M2(MyAction a) => a(); -}", optionName); + void M2(MyAction a) => a(); + } + """, optionName); } [Theory] @@ -3828,25 +4242,27 @@ void M(object p) public async Task UseInLocalFunction_PassedAsArgument_CustomDelegate(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -public delegate void MyAction(); + public delegate void MyAction(); -class C -{ - void M(object p) - { - [|p|] = null; - M2(LocalFunction); + class C + { + void M(object p) + { + [|p|] = null; + M2(LocalFunction); - void LocalFunction() - { - var x = p; - } - } + void LocalFunction() + { + var x = p; + } + } - void M2(MyAction a) => a(); -}", optionName); + void M2(MyAction a) => a(); + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/31744")] @@ -3856,20 +4272,22 @@ public async Task UnusedInExpressionTree_PassedAsArgument(string optionName) { // Currently we bail out of analysis in presence of expression trees. await TestMissingInRegularAndScriptAsync( -@"using System; -using System.Linq.Expressions; + """ + using System; + using System.Linq.Expressions; -class C -{ - public static void M1() - { - object [|p|] = null; - M2(x => x.M3()); - } + class C + { + public static void M1() + { + object [|p|] = null; + M2(x => x.M3()); + } - private static C M2(Expression> a) { return null; } - private int M3() { return 0; } -}", optionName); + private static C M2(Expression> a) { return null; } + private int M3() { return 0; } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/31744")] @@ -3879,20 +4297,22 @@ public async Task ReadInExpressionTree_PassedAsArgument(string optionName) { // Currently we bail out of analysis in presence of expression trees. await TestMissingInRegularAndScriptAsync( -@"using System; -using System.Linq.Expressions; + """ + using System; + using System.Linq.Expressions; -class C -{ - public static void M1() - { - object [|p|] = null; - M2(x => x.M3(p)); - } + class C + { + public static void M1() + { + object [|p|] = null; + M2(x => x.M3(p)); + } - private static C M2(Expression> a) { return null; } - private int M3(object o) { return 0; } -}", optionName); + private static C M2(Expression> a) { return null; } + private int M3(object o) { return 0; } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/31744")] @@ -3902,20 +4322,22 @@ public async Task OnlyWrittenInExpressionTree_PassedAsArgument(string optionName { // Currently we bail out of analysis in presence of expression trees. await TestMissingInRegularAndScriptAsync( -@"using System; -using System.Linq.Expressions; + """ + using System; + using System.Linq.Expressions; -class C -{ - public static void M1() - { - object [|p|] = null; - M2(x => x.M3(out p)); - } + class C + { + public static void M1() + { + object [|p|] = null; + M2(x => x.M3(out p)); + } - private static C M2(Expression> a) { return null; } - private int M3(out object o) { o = null; return 0; } -}", optionName); + private static C M2(Expression> a) { return null; } + private int M3(out object o) { o = null; return 0; } + } + """, optionName); } [Theory] @@ -3924,24 +4346,26 @@ public static void M1() public async Task UseInLambda_PassedAsArgument_CastFromDelegateType(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action a = () => - { - var x = p; - }; + class C + { + void M(object p) + { + Action a = () => + { + var x = p; + }; - object o = a; - [|p|] = null; - M2(o); - } + object o = a; + [|p|] = null; + M2(o); + } - void M2(object a) => ((Action)a)(); -}", optionName); + void M2(object a) => ((Action)a)(); + } + """, optionName); } [Theory] @@ -3950,24 +4374,26 @@ void M(object p) public async Task UseInLocalFunction_PassedAsArgument_CastFromDelegateType(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - object o = (Action)LocalFunction; - [|p|] = null; - M2(o); + class C + { + void M(object p) + { + object o = (Action)LocalFunction; + [|p|] = null; + M2(o); - void LocalFunction() - { - var x = p; - } - } + void LocalFunction() + { + var x = p; + } + } - void M2(object a) => ((Action)a)(); -}", optionName); + void M2(object a) => ((Action)a)(); + } + """, optionName); } [Theory] @@ -3976,21 +4402,23 @@ void LocalFunction() public async Task UseInLambda_DelegateCreationPassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - M2(new Action(() => - { - var x = p; - })); - } + class C + { + void M(object p) + { + [|p|] = null; + M2(new Action(() => + { + var x = p; + })); + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -3999,23 +4427,25 @@ void M(object p) public async Task UseInLocalFunction_DelegateCreationPassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - [|p|] = null; - M2(new Action(LocalFunction)); + class C + { + void M(object p) + { + [|p|] = null; + M2(new Action(LocalFunction)); - void LocalFunction() - { - var x = p; - } - } + void LocalFunction() + { + var x = p; + } + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -4024,23 +4454,25 @@ void LocalFunction() public async Task UseInLambda_DelegatePassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action local = () => - { - var x = p; - }; + class C + { + void M(object p) + { + Action local = () => + { + var x = p; + }; - [|p|] = null; - M2(local); - } + [|p|] = null; + M2(local); + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -4049,24 +4481,26 @@ void M(object p) public async Task UseInLocalFunction_DelegatePassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action local = LocalFunction; - [|p|] = null; - M2(local); + class C + { + void M(object p) + { + Action local = LocalFunction; + [|p|] = null; + M2(local); - void LocalFunction() - { - var x = p; - } - } + void LocalFunction() + { + var x = p; + } + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -4075,25 +4509,27 @@ void LocalFunction() public async Task WrittenInLambda_DelegatePassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, object p2) - { - Action local = () => - { - p = p2; - }; + class C + { + void M(object p, object p2) + { + Action local = () => + { + p = p2; + }; - [|p|] = null; - M2(local); + [|p|] = null; + M2(local); - var x = p; - } + var x = p; + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -4102,25 +4538,27 @@ void M(object p, object p2) public async Task WrittenInLocalFunction_DelegatePassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, object p2) - { - Action local = LocalFunction; - [|p|] = null; - M2(local); - var x = p; + class C + { + void M(object p, object p2) + { + Action local = LocalFunction; + [|p|] = null; + M2(local); + var x = p; - void LocalFunction() - { - p = p2; - } - } + void LocalFunction() + { + p = p2; + } + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -4129,40 +4567,42 @@ void LocalFunction() public async Task WrittenInLambdaAndLocalFunctionTargets_DelegatePassedAsArgument(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, object p2) - { - Action lambda = () => - { - p = p2; - }; + class C + { + void M(object p, object p2) + { + Action lambda = () => + { + p = p2; + }; - Action myDelegate; - if (p2 != null) - { - myDelegate = lambda; - } - else - { - myDelegate = LocalFunction; - } + Action myDelegate; + if (p2 != null) + { + myDelegate = lambda; + } + else + { + myDelegate = LocalFunction; + } - [|p|] = null; - M2(myDelegate); + [|p|] = null; + M2(myDelegate); - var x = p; + var x = p; - void LocalFunction() - { - p = p2; - } - } + void LocalFunction() + { + p = p2; + } + } - void M2(Action a) => a(); -}", optionName); + void M2(Action a) => a(); + } + """, optionName); } [Theory] @@ -4171,19 +4611,21 @@ void LocalFunction() public async Task UseInLambda_ReturnedDelegateCreation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action M(object p) - { - [|p|] = null; - return new Action(() => - { - var x = p; - }); - } -}", optionName); + class C + { + Action M(object p) + { + [|p|] = null; + return new Action(() => + { + var x = p; + }); + } + } + """, optionName); } [Theory] @@ -4192,21 +4634,23 @@ Action M(object p) public async Task UseInLocalFunction_ReturnedDelegateCreation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action M(object p) - { - [|p|] = null; - return new Action(LocalFunction); + class C + { + Action M(object p) + { + [|p|] = null; + return new Action(LocalFunction); - void LocalFunction() - { - var x = p; - }; - } -}", optionName); + void LocalFunction() + { + var x = p; + }; + } + } + """, optionName); } [Theory] @@ -4215,21 +4659,23 @@ void LocalFunction() public async Task UseInLambda_ReturnedDelegate(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action M(object p) - { - Action local = () => - { - var x = p; - }; + class C + { + Action M(object p) + { + Action local = () => + { + var x = p; + }; - [|p|] = null; - return local; - } -}", optionName); + [|p|] = null; + return local; + } + } + """, optionName); } [Theory] @@ -4238,21 +4684,23 @@ Action M(object p) public async Task UseInLocalFunction_ReturnedDelegate(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action M(object p) - { - [|p|] = null; - return LocalFunction; + class C + { + Action M(object p) + { + [|p|] = null; + return LocalFunction; - void LocalFunction() - { - var x = p; - } - } -}", optionName); + void LocalFunction() + { + var x = p; + } + } + } + """, optionName); } [Theory] @@ -4261,24 +4709,26 @@ void LocalFunction() public async Task UseInLambda_InvokedDelegate_ControlFlow(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, bool flag) - { - Action local1 = () => - { - var x = p; - }; + class C + { + void M(object p, bool flag) + { + Action local1 = () => + { + var x = p; + }; - Action local2 = () => { }; + Action local2 = () => { }; - [|p|] = null; - var y = flag ? local1 : local2; - y(); - } -}", optionName); + [|p|] = null; + var y = flag ? local1 : local2; + y(); + } + } + """, optionName); } [Theory] @@ -4287,25 +4737,27 @@ void M(object p, bool flag) public async Task UseInLocalFunction_InvokedDelegate_ControlFlow(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, bool flag) - { - [|p|] = null; - (flag ? LocalFunction1 : (Action)LocalFunction2)(); + class C + { + void M(object p, bool flag) + { + [|p|] = null; + (flag ? LocalFunction1 : (Action)LocalFunction2)(); - void LocalFunction1() - { - var x = p; - } + void LocalFunction1() + { + var x = p; + } - void LocalFunction2() - { - } - } -}", optionName); + void LocalFunction2() + { + } + } + } + """, optionName); } [Theory] @@ -4314,26 +4766,28 @@ void LocalFunction2() public async Task UseInLambda_LambdaAndLocalFunctionTargets(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, bool flag, bool flag2) - { - Action lambda = () => - { - var x = p; - }; + class C + { + void M(object p, bool flag, bool flag2) + { + Action lambda = () => + { + var x = p; + }; - [|p|] = null; - var y = flag ? lambda : (flag2 ? (Action)LocalFunction : M2); - y(); + [|p|] = null; + var y = flag ? lambda : (flag2 ? (Action)LocalFunction : M2); + y(); - void LocalFunction() { } - } + void LocalFunction() { } + } - void M2() { } -}", optionName); + void M2() { } + } + """, optionName); } [Theory] @@ -4344,25 +4798,27 @@ public async Task NotUsed_LambdaAndLocalFunctionTargets(string optionName) // Below should be changed to verify diagnostic/fix once we // perform points-to-analysis for accurate delegate target tracking. await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, bool flag, bool flag2) - { - Action lambda = () => - { - }; + class C + { + void M(object p, bool flag, bool flag2) + { + Action lambda = () => + { + }; - [|p|] = null; - var y = flag ? lambda : (flag2 ? (Action)LocalFunction : M2); - y(); + [|p|] = null; + var y = flag ? lambda : (flag2 ? (Action)LocalFunction : M2); + y(); - void LocalFunction() { } - } + void LocalFunction() { } + } - void M2() { } -}", optionName); + void M2() { } + } + """, optionName); } [Theory] @@ -4371,61 +4827,63 @@ void M2() { } public async Task UseInLambda_LambdaAndLocalFunctionTargets_ThroughLocalsAndParameters(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, bool flag, bool flag2, Action param) - { - Action lambda = () => - { - var x = p; - }; + class C + { + void M(object p, bool flag, bool flag2, Action param) + { + Action lambda = () => + { + var x = p; + }; - [|p|] = null; + [|p|] = null; - Action y; - if (flag) - { - if (flag2) - { - y = (Action)LocalFunction; - } - else - { - y = M2; - } - } - else - { - y = null; - if (flag2) - { - param = lambda; - } - else - { - param = M2; - } - } + Action y; + if (flag) + { + if (flag2) + { + y = (Action)LocalFunction; + } + else + { + y = M2; + } + } + else + { + y = null; + if (flag2) + { + param = lambda; + } + else + { + param = M2; + } + } - Action z; - if (y != null) - { - z = y; - } - else - { - z = param; - } + Action z; + if (y != null) + { + z = y; + } + else + { + z = param; + } - z(); + z(); - void LocalFunction() { } - } + void LocalFunction() { } + } - void M2() { } -}", optionName); + void M2() { } + } + """, optionName); } [Theory] @@ -4434,111 +4892,115 @@ void M2() { } public async Task NotUsed_LambdaAndLocalFunctionTargets_ThroughLocalsAndParameters(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p, bool flag, bool flag2, Action param) - { - Action lambda = () => - { - }; + class C + { + void M(object p, bool flag, bool flag2, Action param) + { + Action lambda = () => + { + }; - [|p|] = null; + [|p|] = null; - Action y; - if (flag) - { - if (flag2) - { - y = (Action)LocalFunction; - } - else - { - y = M2; - } - } - else - { - y = null; - if (flag2) - { - param = lambda; - } - else - { - param = M2; - } - } + Action y; + if (flag) + { + if (flag2) + { + y = (Action)LocalFunction; + } + else + { + y = M2; + } + } + else + { + y = null; + if (flag2) + { + param = lambda; + } + else + { + param = M2; + } + } - Action z; - if (y != null) - { - z = y; - } - else - { - z = param; - } + Action z; + if (y != null) + { + z = y; + } + else + { + z = param; + } - z(); + z(); - void LocalFunction() { } - } + void LocalFunction() { } + } - void M2() { } -}", -@"using System; + void M2() { } + } + """, + """ + using System; -class C -{ - void M(object p, bool flag, bool flag2, Action param) - { - Action lambda = () => - { - }; - Action y; - if (flag) - { - if (flag2) - { - y = (Action)LocalFunction; - } - else - { - y = M2; - } - } - else - { - y = null; - if (flag2) - { - param = lambda; - } - else - { - param = M2; - } - } + class C + { + void M(object p, bool flag, bool flag2, Action param) + { + Action lambda = () => + { + }; + Action y; + if (flag) + { + if (flag2) + { + y = (Action)LocalFunction; + } + else + { + y = M2; + } + } + else + { + y = null; + if (flag2) + { + param = lambda; + } + else + { + param = M2; + } + } - Action z; - if (y != null) - { - z = y; - } - else - { - z = param; - } + Action z; + if (y != null) + { + z = y; + } + else + { + z = param; + } - z(); + z(); - void LocalFunction() { } - } + void LocalFunction() { } + } - void M2() { } -}", optionName); + void M2() { } + } + """, optionName); } [Theory] @@ -4547,22 +5009,23 @@ void M2() { } public async Task AssignedInLambda_UsedAfterInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - int M(int x) - { - Action a = () => - { - [|x|] = 1; - }; - a(); + class C + { + int M(int x) + { + Action a = () => + { + [|x|] = 1; + }; + a(); - return x; - } -} -", optionName); + return x; + } + } + """, optionName); } [Theory] @@ -4571,23 +5034,24 @@ int M(int x) public async Task AssignedInLocalFunction_UsedAfterInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - int M(int x) - { - a(); + class C + { + int M(int x) + { + a(); - return x; + return x; - void a() - { - [|x|] = 1; - } - } -} -", optionName); + void a() + { + [|x|] = 1; + } + } + } + """, optionName); } [Theory] @@ -4596,24 +5060,25 @@ void a() public async Task AssignedInLambda_UsedAfterSecondInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - int M(int x) - { - Action a = () => - { - [|x|] = 1; - }; + class C + { + int M(int x) + { + Action a = () => + { + [|x|] = 1; + }; - a(); - a(); + a(); + a(); - return x; - } -} -", optionName); + return x; + } + } + """, optionName); } [Theory] @@ -4622,24 +5087,25 @@ int M(int x) public async Task AssignedInLocalFunction_UsedAfterSecondInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - int M(int x) - { - a(); - a(); + class C + { + int M(int x) + { + a(); + a(); - return x; + return x; - void a() - { - [|x|] = 1; - } - } -} -", optionName); + void a() + { + [|x|] = 1; + } + } + } + """, optionName); } [Theory] @@ -4648,31 +5114,33 @@ void a() public async Task AssignedInLambda_MayBeUsedAfterOneOfTheInvocations(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - int M(int x, bool flag, bool flag2) - { - Action a = () => - { - [|x|] = 1; - }; + class C + { + int M(int x, bool flag, bool flag2) + { + Action a = () => + { + [|x|] = 1; + }; - a(); + a(); - if (flag) - { - a(); - if (flag2) - { - return x; - } - } + if (flag) + { + a(); + if (flag2) + { + return x; + } + } - return 0; - } -}", optionName); + return 0; + } + } + """, optionName); } [Theory] @@ -4681,31 +5149,33 @@ int M(int x, bool flag, bool flag2) public async Task AssignedInLocalFunction_MayBeUsedAfterOneOfTheInvocations(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - int M(int x, bool flag, bool flag2) - { - a(); + class C + { + int M(int x, bool flag, bool flag2) + { + a(); - if (flag) - { - a(); - if (flag2) - { - return x; - } - } + if (flag) + { + a(); + if (flag2) + { + return x; + } + } - return 0; + return 0; - void a() - { - [|x|] = 1; - } - } -}", optionName); + void a() + { + [|x|] = 1; + } + } + } + """, optionName); } [Theory] @@ -4714,33 +5184,35 @@ void a() public async Task AssignedInLambda_NotUsedAfterInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - Action a = () => - { - [|x|] = 1; - }; - a(); - } -} -", -@"using System; + class C + { + void M(int x) + { + Action a = () => + { + [|x|] = 1; + }; + a(); + } + } + """, + """ + using System; -class C -{ - void M(int x) - { - Action a = () => - { - }; - a(); - } -} -", optionName); + class C + { + void M(int x) + { + Action a = () => + { + }; + a(); + } + } + """, optionName); } [Theory] @@ -4749,33 +5221,37 @@ void M(int x) public async Task AssignedInLocalFunction_NotUsedAfterInvocation(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - a(); + class C + { + void M(int x) + { + a(); - void a() - { - [|x|] = 1; - } - } -}", -@"using System; + void a() + { + [|x|] = 1; + } + } + } + """, + """ + using System; -class C -{ - void M(int x) - { - a(); + class C + { + void M(int x) + { + a(); - void a() - { - } - } -}", optionName); + void a() + { + } + } + } + """, optionName); } [Theory] @@ -4784,22 +5260,24 @@ void a() public async Task UseInLocalFunction_WithRecursiveInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - var x = p; - LocalFunction(); - } + class C + { + void M(object p) + { + void LocalFunction() + { + var x = p; + LocalFunction(); + } - [|p|] = null; - LocalFunction(); - } -}", optionName); + [|p|] = null; + LocalFunction(); + } + } + """, optionName); } [Theory] @@ -4808,21 +5286,23 @@ void LocalFunction() public async Task NotUseInLocalFunction_WithRecursiveInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - void LocalFunction() - { - LocalFunction(); - } + class C + { + void M(object p) + { + void LocalFunction() + { + LocalFunction(); + } - [|p|] = null; - LocalFunction(); - } -}", optionName); + [|p|] = null; + LocalFunction(); + } + } + """, optionName); } [Theory] @@ -4832,23 +5312,25 @@ public async Task Lambda_WithNonReachableExit(string optionName) { // We bail out from analysis for delegate passed an argument. await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action throwEx = () => - { - throw new Exception(); - }; + class C + { + void M(object p) + { + Action throwEx = () => + { + throw new Exception(); + }; - [|p|] = null; - M2(throwEx); - } + [|p|] = null; + M2(throwEx); + } - void M2(Action a) { } -}", optionName); + void M2(Action a) { } + } + """, optionName); } [Theory] @@ -4857,72 +5339,80 @@ void M2(Action a) { } public async Task Lambda_WithMultipleInvocations(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - Action lambda = () => - { - var x = p; - [|p|] = null; // This write is read on next invocation of lambda. - }; + class C + { + void M(object p) + { + Action lambda = () => + { + var x = p; + [|p|] = null; // This write is read on next invocation of lambda. + }; - M2(lambda); - } + M2(lambda); + } - void M2(Action a) - { - a(); - a(); - } -}", optionName); + void M2(Action a) + { + a(); + a(); + } + } + """, optionName); } [Fact] public async Task UnusedValue_DelegateTypeOptionalParameter_PreferDiscard() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - var [|x|] = M2(); - } + class C + { + void M() + { + var [|x|] = M2(); + } - C M2(Action c = null) => null; -}", -@"using System; + C M2(Action c = null) => null; + } + """, + """ + using System; -class C -{ - void M() - { - _ = M2(); - } + class C + { + void M() + { + _ = M2(); + } - C M2(Action c = null) => null; -}", options: PreferDiscard); + C M2(Action c = null) => null; + } + """, options: PreferDiscard); } [Fact] public async Task UnusedValue_DelegateTypeOptionalParameter_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - var [|x|] = M2(); - } + class C + { + void M() + { + var [|x|] = M2(); + } - C M2(Action c = null) => null; -}", options: PreferUnusedLocal); + C M2(Action c = null) => null; + } + """, options: PreferUnusedLocal); } [Theory] @@ -4931,30 +5421,32 @@ void M() public async Task UseInLocalFunction_NestedInvocation(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - LocalFunction(); + """ + class C + { + void M() + { + LocalFunction(); - bool LocalFunction2() - { - return true; - } - - void LocalFunction() - { - object [|p|] = null; - if (LocalFunction2()) - { - } + bool LocalFunction2() + { + return true; + } - if (p != null) - { - } - } - } -}", optionName); + void LocalFunction() + { + object [|p|] = null; + if (LocalFunction2()) + { + } + + if (p != null) + { + } + } + } + } + """, optionName); } [Theory] @@ -4963,124 +5455,138 @@ void LocalFunction() public async Task DeclarationPatternInSwitchCase_WithReadAndWriteReferences(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - switch (p) - { - case int [|x|]: - x = 1; - p = x; - break; - } - } -}", -$@"class C -{{ - void M(object p) - {{ - switch (p) - {{ - case int {fix}: - int x = 1; - p = x; - break; - }} - }} -}}", optionName, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + void M(object p) + { + switch (p) + { + case int [|x|]: + x = 1; + p = x; + break; + } + } + } + """, + $$""" + class C + { + void M(object p) + { + switch (p) + { + case int {{fix}}: + int x = 1; + p = x; + break; + } + } + } + """, optionName, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact] public async Task CatchClause_ExceptionVariable_PreferDiscard() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - try - { - } - catch (Exception [|ex|]) - { - } - } -}", -@"using System; + class C + { + void M(object p) + { + try + { + } + catch (Exception [|ex|]) + { + } + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - try - { - } - catch (Exception) - { - } - } -}", options: PreferDiscard); + class C + { + void M(object p) + { + try + { + } + catch (Exception) + { + } + } + } + """, options: PreferDiscard); } [Fact] public async Task CatchClause_ExceptionVariable_PreferUnusedLocal_01() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - try - { - } - catch (Exception [|ex|]) - { - } - } -}", options: PreferUnusedLocal); + class C + { + void M(object p) + { + try + { + } + catch (Exception [|ex|]) + { + } + } + } + """, options: PreferUnusedLocal); } [Fact] public async Task CatchClause_ExceptionVariable_PreferUnusedLocal_02() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(object p) - { - try - { - } - catch (Exception [|ex|]) - { - ex = null; - var x = ex; - } - } -}", -@"using System; + class C + { + void M(object p) + { + try + { + } + catch (Exception [|ex|]) + { + ex = null; + var x = ex; + } + } + } + """, + """ + using System; -class C -{ - void M(object p) - { - try - { - } - catch (Exception unused) - { - Exception ex = null; - var x = ex; - } - } -}", options: PreferUnusedLocal); + class C + { + void M(object p) + { + try + { + } + catch (Exception unused) + { + Exception ex = null; + var x = ex; + } + } + } + """, options: PreferUnusedLocal); } [Theory] @@ -5089,22 +5595,24 @@ void M(object p) public async Task AssignedOutsideTry_UsedOnlyInCatchClause(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - [|x|] = 0; - try - { - } - catch (Exception) - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + [|x|] = 0; + try + { + } + catch (Exception) + { + var y = x; + } + } + } + """, optionName); } [Theory] @@ -5113,21 +5621,23 @@ void M(int x) public async Task AssignedOutsideTry_UsedOnlyInCatchFilter(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - [|x|] = 0; - try - { - } - catch (Exception) when (x != 0) - { - } - } -}", optionName); + class C + { + void M(int x) + { + [|x|] = 0; + try + { + } + catch (Exception) when (x != 0) + { + } + } + } + """, optionName); } [Theory] @@ -5136,22 +5646,24 @@ void M(int x) public async Task AssignedOutsideTry_UsedOnlyInFinally(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - [|x|] = 0; - try - { - } - finally - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + [|x|] = 0; + try + { + } + finally + { + var y = x; + } + } + } + """, optionName); } [Theory] @@ -5160,22 +5672,24 @@ void M(int x) public async Task AssignedInsideTry_UsedOnlyInCatchClause(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - [|x|] = 0; - } - catch (Exception) - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + try + { + [|x|] = 0; + } + catch (Exception) + { + var y = x; + } + } + } + """, optionName); } [Theory] @@ -5184,25 +5698,27 @@ void M(int x) public async Task AssignedInsideNestedBlockInTry_UsedOnlyInCatchClause(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - if (x > 0) - { - [|x|] = 0; - } - } - catch (Exception) - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + try + { + if (x > 0) + { + [|x|] = 0; + } + } + catch (Exception) + { + var y = x; + } + } + } + """, optionName); } [Theory] @@ -5211,23 +5727,25 @@ void M(int x) public async Task AssignedInCatchClause_UsedAfterTryCatch(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - } - catch (Exception) - { - [|x|] = 0; - } + class C + { + void M(int x) + { + try + { + } + catch (Exception) + { + [|x|] = 0; + } - var y = x; - } -}", optionName); + var y = x; + } + } + """, optionName); } [Theory] @@ -5236,28 +5754,30 @@ void M(int x) public async Task AssignedInNestedCatchClause_UsedInOuterFinally(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - try - { - } - catch (Exception) - { - [|x|] = 0; - } - } - finally - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + try + { + try + { + } + catch (Exception) + { + [|x|] = 0; + } + } + finally + { + var y = x; + } + } + } + """, optionName); } [Theory] @@ -5266,25 +5786,27 @@ void M(int x) public async Task AssignedInCatchClause_UsedInFinally(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - } - catch (Exception) - { - [|x|] = 0; - } - finally - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + try + { + } + catch (Exception) + { + [|x|] = 0; + } + finally + { + var y = x; + } + } + } + """, optionName); } [Theory] @@ -5293,24 +5815,26 @@ void M(int x) public async Task AssignedInCatchFilter_UsedAfterTryCatch(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - } - catch (Exception) when (M2(out [|x|])) - { - } + class C + { + void M(int x) + { + try + { + } + catch (Exception) when (M2(out [|x|])) + { + } - var y = x; - } + var y = x; + } - bool M2(out int x) { x = 0; return true; } -}", optionName); + bool M2(out int x) { x = 0; return true; } + } + """, optionName); } [Theory] @@ -5319,23 +5843,25 @@ void M(int x) public async Task AssignedInFinally_UsedAfterTryFinally(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - } - finally - { - [|x|] = 0; - } + class C + { + void M(int x) + { + try + { + } + finally + { + [|x|] = 0; + } - var y = x; - } -}", optionName); + var y = x; + } + } + """, optionName); } [Theory] @@ -5344,240 +5870,262 @@ void M(int x) public async Task AssignedInNestedFinally_UsedInOuterFinally(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int x) - { - try - { - try - { - } - finally - { - [|x|] = 0; - } - } - finally - { - var y = x; - } - } -}", optionName); + class C + { + void M(int x) + { + try + { + try + { + } + finally + { + [|x|] = 0; + } + } + finally + { + var y = x; + } + } + } + """, optionName); } [Fact] public async Task IfElse_AssignedInCondition_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(bool flag) - { - int x; - if (M2(out [|x|])) - { - x = 2; - } - else - { - x = 3; - } - } + """ + class C + { + void M(bool flag) + { + int x; + if (M2(out [|x|])) + { + x = 2; + } + else + { + x = 3; + } + } - bool M2(out int x) => x = 0; -}", -@"class C -{ - void M(bool flag) - { - int x; - if (M2(out _)) - { - x = 2; - } - else - { - x = 3; - } - } + bool M2(out int x) => x = 0; + } + """, + """ + class C + { + void M(bool flag) + { + int x; + if (M2(out _)) + { + x = 2; + } + else + { + x = 3; + } + } - bool M2(out int x) => x = 0; -}", options: PreferDiscard); + bool M2(out int x) => x = 0; + } + """, options: PreferDiscard); } [Fact] public async Task IfElse_DeclaredInCondition_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(bool flag) - { - if (M2(out var [|x|])) - { - x = 2; - } - else - { - x = 3; - } - } + """ + class C + { + void M(bool flag) + { + if (M2(out var [|x|])) + { + x = 2; + } + else + { + x = 3; + } + } - bool M2(out int x) => x = 0; -}", -@"class C -{ - void M(bool flag) - { - int x; - if (M2(out _)) - { - x = 2; - } - else - { - x = 3; - } - } + bool M2(out int x) => x = 0; + } + """, + """ + class C + { + void M(bool flag) + { + int x; + if (M2(out _)) + { + x = 2; + } + else + { + x = 3; + } + } - bool M2(out int x) => x = 0; -}", options: PreferDiscard); + bool M2(out int x) => x = 0; + } + """, options: PreferDiscard); } [Fact] public async Task IfElseAssignedInCondition_ReadAfter_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M(bool flag) - { - int x; - if (M2(out [|x|])) - { - x = 2; - } - else - { - x = 3; - } + """ + class C + { + int M(bool flag) + { + int x; + if (M2(out [|x|])) + { + x = 2; + } + else + { + x = 3; + } - return x; - } + return x; + } - bool M2(out int x) => x = 0; -}", -@"class C -{ - int M(bool flag) - { - int x; - int unused; - if (M2(out unused)) - { - x = 2; - } - else - { - x = 3; - } + bool M2(out int x) => x = 0; + } + """, + """ + class C + { + int M(bool flag) + { + int x; + int unused; + if (M2(out unused)) + { + x = 2; + } + else + { + x = 3; + } - return x; - } + return x; + } - bool M2(out int x) => x = 0; -}", options: PreferUnusedLocal); + bool M2(out int x) => x = 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task IfElse_AssignedInCondition_NoReads_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(bool flag) - { - int x; - if (M2(out [|x|])) - { - x = 2; - } - else - { - x = 3; - } - } + """ + class C + { + void M(bool flag) + { + int x; + if (M2(out [|x|])) + { + x = 2; + } + else + { + x = 3; + } + } - bool M2(out int x) => x = 0; -}", new TestParameters(options: PreferUnusedLocal)); + bool M2(out int x) => x = 0; + } + """, new TestParameters(options: PreferUnusedLocal)); } [Fact] public async Task IfElse_DeclaredInCondition_ReadAfter_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M(bool flag) - { - if (M2(out var [|x|])) - { - x = 2; - } - else - { - x = 3; - } + """ + class C + { + int M(bool flag) + { + if (M2(out var [|x|])) + { + x = 2; + } + else + { + x = 3; + } - return x; - } + return x; + } - bool M2(out int x) => x = 0; -}", -@"class C -{ - int M(bool flag) - { - int x; - if (M2(out var unused)) - { - x = 2; - } - else - { - x = 3; - } + bool M2(out int x) => x = 0; + } + """, + """ + class C + { + int M(bool flag) + { + int x; + if (M2(out var unused)) + { + x = 2; + } + else + { + x = 3; + } - return x; - } + return x; + } - bool M2(out int x) => x = 0; -}", options: PreferUnusedLocal); + bool M2(out int x) => x = 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task IfElse_DeclaredInCondition_NoReads_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(bool flag) - { - if (M2(out var [|x|])) - { - x = 2; - } - else - { - x = 3; - } - } + """ + class C + { + void M(bool flag) + { + if (M2(out var [|x|])) + { + x = 2; + } + else + { + x = 3; + } + } - bool M2(out int x) => x = 0; -}", new TestParameters(options: PreferUnusedLocal)); + bool M2(out int x) => x = 0; + } + """, new TestParameters(options: PreferUnusedLocal)); } [Theory] @@ -5598,40 +6146,44 @@ void M(bool flag) public async Task IfElse_OverwrittenInAllControlFlowPaths(string ifBranchCode, string elseBranchCode) { await TestInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(bool flag, bool flag2, bool flag3) - {{ - int [|x|] = 1; - if (flag4) - {{ - {ifBranchCode} - }} - else - {{ - {elseBranchCode} - }} - - return x; - }} -}}", -$@"class C -{{ - int M(bool flag, bool flag2, bool flag3) - {{ - int x; - if (flag4) - {{ - {ifBranchCode} - }} - else - {{ - {elseBranchCode} - }} + $$""" + class C + { + int M(bool flag, bool flag2, bool flag3) + { + int [|x|] = 1; + if (flag4) + { + {{ifBranchCode}} + } + else + { + {{elseBranchCode}} + } - return x; - }} -}}"); + return x; + } + } + """, + $$""" + class C + { + int M(bool flag, bool flag2, bool flag3) + { + int x; + if (flag4) + { + {{ifBranchCode}} + } + else + { + {{elseBranchCode}} + } + + return x; + } + } + """); } [Theory] @@ -5654,23 +6206,25 @@ int M(bool flag, bool flag2, bool flag3) public async Task IfElse_OverwrittenInSomeControlFlowPaths(string ifBranchCode, string elseBranchCode) { await TestMissingInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(bool flag, bool flag2, bool flag3) - {{ - int [|x|] = 1; - if (flag4) - {{ - {ifBranchCode} - }} - else - {{ - {elseBranchCode} - }} + $$""" + class C + { + int M(bool flag, bool flag2, bool flag3) + { + int [|x|] = 1; + if (flag4) + { + {{ifBranchCode}} + } + else + { + {{elseBranchCode}} + } - return x; - }} -}}"); + return x; + } + } + """); } [Theory] @@ -5681,46 +6235,50 @@ int M(bool flag, bool flag2, bool flag3) public async Task IfElse_Overwritten_CodeInOneBranch_ConditionInOtherBranch(string condition, string ifBranchCode, string elseBranchCode) { await TestInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(bool flag) - {{ - int [|x|] = 1; - if ({condition}) - {{ - {ifBranchCode} - }} - else - {{ - {elseBranchCode} - }} + $$""" + class C + { + int M(bool flag) + { + int [|x|] = 1; + if ({{condition}}) + { + {{ifBranchCode}} + } + else + { + {{elseBranchCode}} + } - return x; - }} - - bool M2(out int x) {{ x = 0; return true; }} - int M3() => 0; -}}", -$@"class C -{{ - int M(bool flag) - {{ - int x; - if ({condition}) - {{ - {ifBranchCode} - }} - else - {{ - {elseBranchCode} - }} + return x; + } - return x; - }} + bool M2(out int x) { x = 0; return true; } + int M3() => 0; + } + """, + $$""" + class C + { + int M(bool flag) + { + int x; + if ({{condition}}) + { + {{ifBranchCode}} + } + else + { + {{elseBranchCode}} + } + + return x; + } - bool M2(out int x) {{ x = 0; return true; }} - int M3() => 0; -}}"); + bool M2(out int x) { x = 0; return true; } + int M3() => 0; + } + """); } [Theory] @@ -5733,24 +6291,26 @@ int M(bool flag) public async Task IfElse_MayBeOverwrittenInCondition_LogicalOperators(string condition) { await TestMissingInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(bool flag) - {{ - int [|x|] = 1; - if ({condition}) - {{ - }} - else - {{ - }} + $$""" + class C + { + int M(bool flag) + { + int [|x|] = 1; + if ({{condition}}) + { + } + else + { + } - return x; - }} + return x; + } - bool M2(out int x) {{ x = 0; return true; }} - int M3() => 0; -}}"); + bool M2(out int x) { x = 0; return true; } + int M3() => 0; + } + """); } [Theory] @@ -5765,42 +6325,46 @@ int M(bool flag) public async Task IfElse_OverwrittenInCondition_LogicalOperators(string condition) { await TestInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(bool flag) - {{ - int [|x|] = 1; - if ({condition}) - {{ - }} - else - {{ - }} + $$""" + class C + { + int M(bool flag) + { + int [|x|] = 1; + if ({{condition}}) + { + } + else + { + } - return x; - }} - - bool M2(out int x) {{ x = 0; return true; }} - int M3() => 0; -}}", - $@"class C -{{ - int M(bool flag) - {{ - int x; - if ({condition}) - {{ - }} - else - {{ - }} + return x; + } - return x; - }} + bool M2(out int x) { x = 0; return true; } + int M3() => 0; + } + """, + $$""" + class C + { + int M(bool flag) + { + int x; + if ({{condition}}) + { + } + else + { + } + + return x; + } - bool M2(out int x) {{ x = 0; return true; }} - int M3() => 0; -}}"); + bool M2(out int x) { x = 0; return true; } + int M3() => 0; + } + """); } [Theory] @@ -5809,19 +6373,21 @@ int M(bool flag) public async Task ElselessIf(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M(bool flag) - { - int [|x|] = 1; - if (flag) - { - x = 1; - } + """ + class C + { + int M(bool flag) + { + int [|x|] = 1; + if (flag) + { + x = 1; + } - return x; - } -}", optionName); + return x; + } + } + """, optionName); } [Theory] @@ -5830,89 +6396,97 @@ int M(bool flag) public async Task UnusedDefinition_NotFlagged_InUnreachableBlock(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int x; - if (true) - { - x = 0; - } - else - { - [|x|] = 1; - } + """ + class C + { + void M() + { + int x; + if (true) + { + x = 0; + } + else + { + [|x|] = 1; + } - return x; - } -} + return x; + } + } - bool M2(out int x) { x = 0; return true; } -}", optionName); + bool M2(out int x) { x = 0; return true; } + } + """, optionName); } [Fact] public async Task SwitchCase_UnusedValueWithOnlyWrite_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M(int flag) - { - switch(flag) - { - case 0: - int [|x|] = M2(); - return 0; + """ + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + int [|x|] = M2(); + return 0; - default: - return flag; - } - } + default: + return flag; + } + } - int M2() => 0; -}", -@"class C -{ - int M(int flag) - { - switch(flag) - { - case 0: - _ = M2(); - return 0; + int M2() => 0; + } + """, + """ + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + _ = M2(); + return 0; - default: - return flag; - } - } + default: + return flag; + } + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task SwitchCase_UnusedValueWithOnlyWrite_PreferUnusedLocal() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - int M(int flag) - { - switch(flag) - { - case 0: - int [|x|] = M2(); - return 0; + """ + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + int [|x|] = M2(); + return 0; - default: - return flag; - } - } + default: + return flag; + } + } - int M2() => 0; -}", options: PreferUnusedLocal); + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Theory] @@ -5921,41 +6495,45 @@ int M(int flag) public async Task SwitchCase_UnusedConstantValue_WithReadsAndWrites(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M(int flag) - { - switch(flag) - { - case 0: - int [|x|] = 0; - x = 1; - return x; + """ + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + int [|x|] = 0; + x = 1; + return x; - default: - return flag; - } - } + default: + return flag; + } + } - int M2() => 0; -}", -@"class C -{ - int M(int flag) - { - switch(flag) - { - case 0: - int x = 1; - return x; + int M2() => 0; + } + """, + """ + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + int x = 1; + return x; - default: - return flag; - } - } + default: + return flag; + } + } - int M2() => 0; -}", optionName); + int M2() => 0; + } + """, optionName); } [Theory] @@ -5964,42 +6542,46 @@ int M(int flag) public async Task SwitchCase_UnusedNonConstantValue_WithReadsAndWrites(string optionName, string fix) { await TestInRegularAndScriptAsync( -@"class C -{ - int M(int flag) - { - switch(flag) - { - case 0: - int [|x|] = M2(); - x = 1; - return x; + """ + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + int [|x|] = M2(); + x = 1; + return x; - default: - return flag; - } - } + default: + return flag; + } + } - int M2() => 0; -}", -$@"class C -{{ - int M(int flag) - {{ - switch(flag) - {{ - case 0: - {fix} = M2(); - int x = 1; - return x; + int M2() => 0; + } + """, + $$""" + class C + { + int M(int flag) + { + switch(flag) + { + case 0: + {{fix}} = M2(); + int x = 1; + return x; - default: - return flag; - }} - }} + default: + return flag; + } + } - int M2() => 0; -}}", optionName); + int M2() => 0; + } + """, optionName); } [Theory] @@ -6017,32 +6599,38 @@ int M(int flag) [InlineData("while(i++ < 10)", "M2(x); [|x|] = 1; if (flag) continue; x = 2;")] // Break. - [InlineData(@"x = 0; - while(i++ < 10)", + [InlineData(""" + x = 0; + while(i++ < 10) + """, "[|x|] = 1; if (flag) break; x = 2;")] // Assignment before loop, no overwrite on path where loop is never entered. - [InlineData(@"[|x|] = 1; - while(i++ < 10)", + [InlineData(""" + [|x|] = 1; + while(i++ < 10) + """, "x = 2;")] public async Task Loops_Overwritten_InSomeControlFlowPaths( string loopHeader, string loopBody, string? loopFooter = null) { await TestMissingInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(int i, int x, bool flag) - {{ - {loopHeader} - {{ - {loopBody} - }} - {loopFooter ?? string.Empty} + $$""" + class C + { + int M(int i, int x, bool flag) + { + {{loopHeader}} + { + {{loopBody}} + } + {{loopFooter ?? string.Empty}} - return x; - }} + return x; + } - void M2(int x) {{ }} -}}"); + void M2(int x) { } + } + """); } [Theory] @@ -6063,252 +6651,272 @@ void M2(int x) {{ }} "M2(x);", "x = 3;")] // Assigned before loop, Re-assigned in continue, break paths and loop exit. - [InlineData(@"[|x|] = 1; - i = 1; - while(i++ < 10)", - @"if(flag) - { x = 2; continue; } - else if(i < 5) - { break; } - else - { x = 3; } - M2(x);", + [InlineData(""" + [|x|] = 1; + i = 1; + while(i++ < 10) + """, + """ + if(flag) + { x = 2; continue; } + else if(i < 5) + { break; } + else + { x = 3; } + M2(x); + """, "x = 4;", // Fixed code. - @"i = 1; - while(i++ < 10)", - @"if(flag) - { x = 2; continue; } - else if(i < 5) - { break; } - else - { x = 3; } - M2(x);", + """ + i = 1; + while(i++ < 10) + """, + """ + if(flag) + { x = 2; continue; } + else if(i < 5) + { break; } + else + { x = 3; } + M2(x); + """, "x = 4;")] public async Task Loops_Overwritten_InAllControlFlowPaths( string loopHeader, string loopBody, string loopFooter, string fixedLoopHeader, string fixedLoopBody, string fixedLoopFooter) { await TestInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(int i, int x, bool flag) - {{ - {loopHeader} - {{ - {loopBody} - }} - {loopFooter} + $$""" + class C + { + int M(int i, int x, bool flag) + { + {{loopHeader}} + { + {{loopBody}} + } + {{loopFooter}} - return x; - }} - - void M2(int x) {{ }} -}}", -$@"class C -{{ - int M(int i, int x, bool flag) - {{ - {fixedLoopHeader} - {{ - {fixedLoopBody} - }} - {fixedLoopFooter} + return x; + } - return x; - }} + void M2(int x) { } + } + """, + $$""" + class C + { + int M(int i, int x, bool flag) + { + {{fixedLoopHeader}} + { + {{fixedLoopBody}} + } + {{fixedLoopFooter}} - void M2(int x) {{ }} -}}"); + return x; + } + + void M2(int x) { } + } + """); } [Fact] public async Task FixAll_NonConstantValue_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - public C() - { - // Different code block - int x = M2(); - } + """ + class C + { + public C() + { + // Different code block + int x = M2(); + } - int M(bool flag) - { - // Trigger diagostic - {|FixAllInDocument:int x = M2()|}; + int M(bool flag) + { + // Trigger diagostic + {|FixAllInDocument:int x = M2()|}; - // Unused out assignment - M2(out x); + // Unused out assignment + M2(out x); - // Used Assignment - x = 0; - System.Console.WriteLine(x); + // Used Assignment + x = 0; + System.Console.WriteLine(x); - // Unused constant assignment. - // Not fixed as we have a different code fix 'Remove redundant assignment' - x = 1; + // Unused constant assignment. + // Not fixed as we have a different code fix 'Remove redundant assignment' + x = 1; - // Unused initialization with only def/use in nested block. - // Declaration for 'y' should be moved inside the if block. - int y = M2(); - if (flag) - { - y = 2; - System.Console.WriteLine(y); - } - else - { - } + // Unused initialization with only def/use in nested block. + // Declaration for 'y' should be moved inside the if block. + int y = M2(); + if (flag) + { + y = 2; + System.Console.WriteLine(y); + } + else + { + } - x = M2(); - return x; - } + x = M2(); + return x; + } - bool M2(out int x) { x = 0; return true; } - int M2() => 0; -}", -@"class C -{ - public C() - { - // Different code block - _ = M2(); - } + bool M2(out int x) { x = 0; return true; } + int M2() => 0; + } + """, + """ + class C + { + public C() + { + // Different code block + _ = M2(); + } - int M(bool flag) - { - // Trigger diagostic - _ = M2(); + int M(bool flag) + { + // Trigger diagostic + _ = M2(); - // Unused out assignment - M2(out _); + // Unused out assignment + M2(out _); - // Used Assignment - int x = 0; - System.Console.WriteLine(x); + // Used Assignment + int x = 0; + System.Console.WriteLine(x); - // Unused constant assignment. - // Not fixed as we have a different code fix 'Remove redundant assignment' - x = 1; + // Unused constant assignment. + // Not fixed as we have a different code fix 'Remove redundant assignment' + x = 1; - // Unused initialization with only def/use in nested block. - // Declaration for 'y' should be moved inside the if block. - _ = M2(); - if (flag) - { - int y = 2; - System.Console.WriteLine(y); - } - else - { - } + // Unused initialization with only def/use in nested block. + // Declaration for 'y' should be moved inside the if block. + _ = M2(); + if (flag) + { + int y = 2; + System.Console.WriteLine(y); + } + else + { + } - x = M2(); - return x; - } + x = M2(); + return x; + } - bool M2(out int x) { x = 0; return true; } - int M2() => 0; -}", options: PreferDiscard); + bool M2(out int x) { x = 0; return true; } + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task FixAll_NonConstantValue_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - public C() - { - // Different code block - int x = M2(); - x = 0; - System.Console.WriteLine(x); - } + """ + class C + { + public C() + { + // Different code block + int x = M2(); + x = 0; + System.Console.WriteLine(x); + } - int M(bool flag) - { - // Trigger diagostic - {|FixAllInDocument:int x = M2()|}; + int M(bool flag) + { + // Trigger diagostic + {|FixAllInDocument:int x = M2()|}; - // Unused out assignment - M2(out x); + // Unused out assignment + M2(out x); - // Used Assignment, declaration for 'x' should move here - x = 0; - System.Console.WriteLine(x); + // Used Assignment, declaration for 'x' should move here + x = 0; + System.Console.WriteLine(x); - // Unused constant assignment. - // Not fixed as we have a different code fix 'Remove redundant assignment' - x = 1; + // Unused constant assignment. + // Not fixed as we have a different code fix 'Remove redundant assignment' + x = 1; - // Unused initialization with only def/use in nested block. - // Declaration for 'y' should be moved inside the if block. - int y = M2(); - if (flag) - { - y = 2; - System.Console.WriteLine(y); - } - else - { - } + // Unused initialization with only def/use in nested block. + // Declaration for 'y' should be moved inside the if block. + int y = M2(); + if (flag) + { + y = 2; + System.Console.WriteLine(y); + } + else + { + } - x = M2(); - return x; - } + x = M2(); + return x; + } - bool M2(out int x) { x = 0; return true; } - int M2() => 0; -}", -@"class C -{ - public C() - { - // Different code block - int unused = M2(); - int x = 0; - System.Console.WriteLine(x); - } + bool M2(out int x) { x = 0; return true; } + int M2() => 0; + } + """, + """ + class C + { + public C() + { + // Different code block + int unused = M2(); + int x = 0; + System.Console.WriteLine(x); + } - int M(bool flag) - { - // Trigger diagostic - int unused = M2(); - int unused1; + int M(bool flag) + { + // Trigger diagostic + int unused = M2(); + int unused1; - // Unused out assignment - M2(out unused1); + // Unused out assignment + M2(out unused1); - // Used Assignment, declaration for 'x' should move here - int x = 0; - System.Console.WriteLine(x); + // Used Assignment, declaration for 'x' should move here + int x = 0; + System.Console.WriteLine(x); - // Unused constant assignment. - // Not fixed as we have a different code fix 'Remove redundant assignment' - x = 1; + // Unused constant assignment. + // Not fixed as we have a different code fix 'Remove redundant assignment' + x = 1; - // Unused initialization with only def/use in nested block. - // Declaration for 'y' should be moved inside the if block. - int unused2 = M2(); - if (flag) - { - int y = 2; - System.Console.WriteLine(y); - } - else - { - } + // Unused initialization with only def/use in nested block. + // Declaration for 'y' should be moved inside the if block. + int unused2 = M2(); + if (flag) + { + int y = 2; + System.Console.WriteLine(y); + } + else + { + } - x = M2(); - return x; - } + x = M2(); + return x; + } - bool M2(out int x) { x = 0; return true; } - int M2() => 0; -}", options: PreferUnusedLocal); + bool M2(out int x) { x = 0; return true; } + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Theory] @@ -6317,356 +6925,384 @@ int M(bool flag) public async Task FixAll_ConstantValue_RemoveRedundantAssignments(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - public C() - { - // Different code block - int x = 1; - } + """ + class C + { + public C() + { + // Different code block + int x = 1; + } - int M(bool flag, int p) - { - // Trigger diagostic - {|FixAllInDocument:int x = 0|}; + int M(bool flag, int p) + { + // Trigger diagostic + {|FixAllInDocument:int x = 0|}; - // Unused assignment from parameter, should be removed. - x = p; + // Unused assignment from parameter, should be removed. + x = p; - // Unused assignment from local, should be removed. - int local = 3; - x = local; + // Unused assignment from local, should be removed. + int local = 3; + x = local; - // Used assignment, declaration for 'x' should move here - x = 0; - System.Console.WriteLine(x); + // Used assignment, declaration for 'x' should move here + x = 0; + System.Console.WriteLine(x); - // Unused non-constant 'out' assignment - // Not fixed as we have a different code fix 'Use discard' for it. - M2(out x); + // Unused non-constant 'out' assignment + // Not fixed as we have a different code fix 'Use discard' for it. + M2(out x); - // Unused initialization with only def/use in nested block. - // Declaration for 'y' should be moved inside the if block. - int y = 1; - if (flag) - { - y = 2; - System.Console.WriteLine(y); - } - else - { - } + // Unused initialization with only def/use in nested block. + // Declaration for 'y' should be moved inside the if block. + int y = 1; + if (flag) + { + y = 2; + System.Console.WriteLine(y); + } + else + { + } - x = M2(); - return x; - } + x = M2(); + return x; + } - bool M2(out int x) { x = 0; return true; } - int M2() => 0; -}", -@"class C -{ - public C() - { - // Different code block - } + bool M2(out int x) { x = 0; return true; } + int M2() => 0; + } + """, + """ + class C + { + public C() + { + // Different code block + } - int M(bool flag, int p) - { + int M(bool flag, int p) + { - // Unused assignment from parameter, should be removed. + // Unused assignment from parameter, should be removed. - // Unused assignment from local, should be removed. - int local = 3; + // Unused assignment from local, should be removed. + int local = 3; - // Trigger diagostic - // Used assignment, declaration for 'x' should move here - int x = 0; - System.Console.WriteLine(x); + // Trigger diagostic + // Used assignment, declaration for 'x' should move here + int x = 0; + System.Console.WriteLine(x); - // Unused non-constant 'out' assignment - // Not fixed as we have a different code fix 'Use discard' for it. - M2(out x); - if (flag) - { - // Unused initialization with only def/use in nested block. - // Declaration for 'y' should be moved inside the if block. - int y = 2; - System.Console.WriteLine(y); - } - else - { - } + // Unused non-constant 'out' assignment + // Not fixed as we have a different code fix 'Use discard' for it. + M2(out x); + if (flag) + { + // Unused initialization with only def/use in nested block. + // Declaration for 'y' should be moved inside the if block. + int y = 2; + System.Console.WriteLine(y); + } + else + { + } - x = M2(); - return x; - } + x = M2(); + return x; + } - bool M2(out int x) { x = 0; return true; } - int M2() => 0; -}", optionName); + bool M2(out int x) { x = 0; return true; } + int M2() => 0; + } + """, optionName); } [Fact] public async Task FixAll_MoveMultipleVariableDeclarations_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - int M(bool flag, int p) - { - // Multiple unused variable declarations (x and y) moved below to start of if-else block - // Used declaration (z1) and evaluation (_ = M2()) retained. - // Completely unused declaration (z2) removed. - {|FixAllInDocument:int x = 0|}; - int z1 = 1, _ = M2(), y = 0, z2 = 2; - - if (flag) - { - x = 1; - y = 1; - } - else - { - x = 2; - y = 2; - } + """ + class C + { + int M(bool flag, int p) + { + // Multiple unused variable declarations (x and y) moved below to start of if-else block + // Used declaration (z1) and evaluation (_ = M2()) retained. + // Completely unused declaration (z2) removed. + {|FixAllInDocument:int x = 0|}; + int z1 = 1, _ = M2(), y = 0, z2 = 2; - return x + y + z1; - } + if (flag) + { + x = 1; + y = 1; + } + else + { + x = 2; + y = 2; + } - int M2() => 0; -}", -@"class C -{ - int M(bool flag, int p) - { - int z1 = 1; - _ = M2(); + return x + y + z1; + } - // Multiple unused variable declarations (x and y) moved below to start of if-else block - // Used declaration (z1) and evaluation (_ = M2()) retained. - // Completely unused declaration (z2) removed. - int x; - int y; - if (flag) - { - x = 1; - y = 1; - } - else - { - x = 2; - y = 2; - } + int M2() => 0; + } + """, + """ + class C + { + int M(bool flag, int p) + { + int z1 = 1; + _ = M2(); + + // Multiple unused variable declarations (x and y) moved below to start of if-else block + // Used declaration (z1) and evaluation (_ = M2()) retained. + // Completely unused declaration (z2) removed. + int x; + int y; + if (flag) + { + x = 1; + y = 1; + } + else + { + x = 2; + y = 2; + } - return x + y + z1; - } + return x + y + z1; + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task FixAll_MoveMultipleVariableDeclarations_PreferUnusedLocal() { await TestInRegularAndScriptAsync( -@"class C -{ - int M(bool flag, int p) - { - // Multiple unused variable declarations (x and y) moved below to start of if-else block - // Used declaration (z1) and evaluation (_ = M2()) retained. - // Completely unused declaration (z2) removed. - {|FixAllInDocument:int x = 0|}; - int z1 = 1, _ = M2(), y = 0, z2 = 2; - - if (flag) - { - x = 1; - y = 1; - } - else - { - x = 2; - y = 2; - } + """ + class C + { + int M(bool flag, int p) + { + // Multiple unused variable declarations (x and y) moved below to start of if-else block + // Used declaration (z1) and evaluation (_ = M2()) retained. + // Completely unused declaration (z2) removed. + {|FixAllInDocument:int x = 0|}; + int z1 = 1, _ = M2(), y = 0, z2 = 2; - return x + y + z1; - } + if (flag) + { + x = 1; + y = 1; + } + else + { + x = 2; + y = 2; + } - int M2() => 0; -}", -@"class C -{ - int M(bool flag, int p) - { - int z1 = 1, _ = M2(); + return x + y + z1; + } - // Multiple unused variable declarations (x and y) moved below to start of if-else block - // Used declaration (z1) and evaluation (_ = M2()) retained. - // Completely unused declaration (z2) removed. - int x; - int y; - if (flag) - { - x = 1; - y = 1; - } - else - { - x = 2; - y = 2; - } + int M2() => 0; + } + """, + """ + class C + { + int M(bool flag, int p) + { + int z1 = 1, _ = M2(); + + // Multiple unused variable declarations (x and y) moved below to start of if-else block + // Used declaration (z1) and evaluation (_ = M2()) retained. + // Completely unused declaration (z2) removed. + int x; + int y; + if (flag) + { + x = 1; + y = 1; + } + else + { + x = 2; + y = 2; + } - return x + y + z1; - } + return x + y + z1; + } - int M2() => 0; -}", options: PreferUnusedLocal); + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task NonConstantValue_Trivia_PreferDiscard_01() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - // C1 - [|int x = M2()|], y = M2(); // C2 - // C3 + """ + class C + { + int M() + { + // C1 + [|int x = M2()|], y = M2(); // C2 + // C3 - return y; - } + return y; + } - int M2() => 0; -}", -@"class C -{ - int M() - { - // C1 - _ = M2(); - // C1 - int y = M2(); // C2 - // C3 + int M2() => 0; + } + """, + """ + class C + { + int M() + { + // C1 + _ = M2(); + // C1 + int y = M2(); // C2 + // C3 - return y; - } + return y; + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task NonConstantValue_Trivia_PreferDiscard_02() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - /*C1*/ - /*C2*/[|int/*C3*/ /*C4*/x/*C5*/ = /*C6*/M2()|]/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 - /*C11*/ + """ + class C + { + int M() + { + /*C1*/ + /*C2*/[|int/*C3*/ /*C4*/x/*C5*/ = /*C6*/M2()|]/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 + /*C11*/ - return y; - } + return y; + } - int M2() => 0; -}", -@"class C -{ - int M() - { - /*C1*/ - /*C2*//*C3*/ /*C4*/ - _/*C5*/ = /*C6*/M2()/*C7*/; - /*C1*/ - /*C2*/ - int/*C3*/ /*C4*/y/*C8*/ = M2()/*C9*/; // C10 - /*C11*/ - - return y; - } + int M2() => 0; + } + """, + """ + class C + { + int M() + { + /*C1*/ + /*C2*//*C3*/ /*C4*/ + _/*C5*/ = /*C6*/M2()/*C7*/; + /*C1*/ + /*C2*/ + int/*C3*/ /*C4*/y/*C8*/ = M2()/*C9*/; // C10 + /*C11*/ + + return y; + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task NonConstantValue_Trivia_PreferUnusedLocal_01() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - // C1 - [|int x = M2()|], y = M2(); // C2 - // C3 + """ + class C + { + int M() + { + // C1 + [|int x = M2()|], y = M2(); // C2 + // C3 - // C4 - x = 1; - return x + y; - } + // C4 + x = 1; + return x + y; + } - int M2() => 0; -}", -@"class C -{ - int M() - { - // C1 - int unused = M2(), y = M2(); // C2 - // C3 + int M2() => 0; + } + """, + """ + class C + { + int M() + { + // C1 + int unused = M2(), y = M2(); // C2 + // C3 - // C4 - int x = 1; - return x + y; - } + // C4 + int x = 1; + return x + y; + } - int M2() => 0; -}", options: PreferUnusedLocal); + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task NonConstantValue_Trivia_PreferUnusedLocal_02() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - /*C1*/ - /*C2*/[|int/*C3*/ /*C4*/x/*C5*/ = /*C6*/M2()|]/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 - /*C11*/ + """ + class C + { + int M() + { + /*C1*/ + /*C2*/[|int/*C3*/ /*C4*/x/*C5*/ = /*C6*/M2()|]/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 + /*C11*/ - // C12 - x = 1; - return x + y; - } + // C12 + x = 1; + return x + y; + } - int M2() => 0; -}", -@"class C -{ - int M() - { - /*C1*/ - /*C2*/ - int/*C3*/ /*C4*/unused/*C5*/ = /*C6*/M2()/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 - /*C11*/ - - // C12 - int x = 1; - return x + y; - } + int M2() => 0; + } + """, + """ + class C + { + int M() + { + /*C1*/ + /*C2*/ + int/*C3*/ /*C4*/unused/*C5*/ = /*C6*/M2()/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 + /*C11*/ + + // C12 + int x = 1; + return x + y; + } - int M2() => 0; -}", options: PreferUnusedLocal); + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Theory] @@ -6675,36 +7311,40 @@ int M() public async Task ConstantValue_Trivia_01(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - // C1 - [|int x = 0|], y = M2(); // C2 - // C3 + """ + class C + { + int M() + { + // C1 + [|int x = 0|], y = M2(); // C2 + // C3 - // C4 - x = 1; - return x + y; - } + // C4 + x = 1; + return x + y; + } - int M2() => 0; -}", -@"class C -{ - int M() - { - // C1 - int y = M2(); // C2 - // C3 + int M2() => 0; + } + """, + """ + class C + { + int M() + { + // C1 + int y = M2(); // C2 + // C3 - // C4 - int x = 1; - return x + y; - } + // C4 + int x = 1; + return x + y; + } - int M2() => 0; -}", optionName); + int M2() => 0; + } + """, optionName); } [Theory] @@ -6713,117 +7353,129 @@ int M() public async Task ConstantValue_Trivia_02(string optionName) { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - /*C1*/ - /*C2*/[|int/*C3*/ /*C4*/x/*C5*/ = /*C6*/0|]/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 - /*C11*/ - - // C12 - x = 1; - return x + y; - } + """ + class C + { + int M() + { + /*C1*/ + /*C2*/[|int/*C3*/ /*C4*/x/*C5*/ = /*C6*/0|]/*C7*/, y/*C8*/ = M2()/*C9*/; // C10 + /*C11*/ - int M2() => 0; -}", -@"class C -{ - int M() - { - /*C1*/ - /*C2*/ - int/*C3*/ /*C4*/y/*C8*/ = M2()/*C9*/; // C10 - /*C11*/ - - // C12 - int x = 1; - return x + y; - } + // C12 + x = 1; + return x + y; + } - int M2() => 0; -}", optionName); + int M2() => 0; + } + """, + """ + class C + { + int M() + { + /*C1*/ + /*C2*/ + int/*C3*/ /*C4*/y/*C8*/ = M2()/*C9*/; // C10 + /*C11*/ + + // C12 + int x = 1; + return x + y; + } + + int M2() => 0; + } + """, optionName); } [Fact] public async Task ExistingDiscardDeclarationInLambda_UseOutsideLambda() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - int [|x|] = M2(); - Action a = () => - { - var _ = M2(); - }; + class C + { + void M() + { + int [|x|] = M2(); + Action a = () => + { + var _ = M2(); + }; - a(); - } + a(); + } - int M2() => 0; -}", -@"using System; + int M2() => 0; + } + """, + """ + using System; -class C -{ - void M() - { - _ = M2(); - Action a = () => - { - _ = M2(); - }; + class C + { + void M() + { + _ = M2(); + Action a = () => + { + _ = M2(); + }; - a(); - } + a(); + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Fact] public async Task ExistingDiscardDeclarationInLambda_UseInsideLambda() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - Action a = () => - { - int [|x|] = M2(); - var _ = M2(); - }; + class C + { + void M() + { + Action a = () => + { + int [|x|] = M2(); + var _ = M2(); + }; - a(); - } + a(); + } - int M2() => 0; -}", -@"using System; + int M2() => 0; + } + """, + """ + using System; -class C -{ - void M() - { - Action a = () => - { - _ = M2(); - _ = M2(); - }; + class C + { + void M() + { + Action a = () => + { + _ = M2(); + _ = M2(); + }; - a(); - } + a(); + } - int M2() => 0; -}", options: PreferDiscard); + int M2() => 0; + } + """, options: PreferDiscard); } [Theory] @@ -6832,61 +7484,65 @@ void M() public async Task ValueOverwrittenByOutVar_ConditionalAndExpression(string optionName) { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - int {|FixAllInDocument:x1|} = -1, x2 = -1; - if (M2(x: out x1) && - M2(x: out x2)) - { - x1 = 0; - x2 = 0; - } - else - { - Console.WriteLine(x1); - } + class C + { + void M() + { + int {|FixAllInDocument:x1|} = -1, x2 = -1; + if (M2(x: out x1) && + M2(x: out x2)) + { + x1 = 0; + x2 = 0; + } + else + { + Console.WriteLine(x1); + } - Console.WriteLine(x1 + x2); - } + Console.WriteLine(x1 + x2); + } - bool M2(out int x) - { - x = 0; - return true; - } -}", -@"using System; + bool M2(out int x) + { + x = 0; + return true; + } + } + """, + """ + using System; -class C -{ - void M() - { - int x2 = -1; - int x1; - if (M2(x: out x1) && - M2(x: out x2)) - { - x1 = 0; - x2 = 0; - } - else - { - Console.WriteLine(x1); - } + class C + { + void M() + { + int x2 = -1; + int x1; + if (M2(x: out x1) && + M2(x: out x2)) + { + x1 = 0; + x2 = 0; + } + else + { + Console.WriteLine(x1); + } - Console.WriteLine(x1 + x2); - } + Console.WriteLine(x1 + x2); + } - bool M2(out int x) - { - x = 0; - return true; - } -}", optionName); + bool M2(out int x) + { + x = 0; + return true; + } + } + """, optionName); } [Theory] @@ -6895,84 +7551,92 @@ bool M2(out int x) public async Task UnusedOutVariableDeclaration_PreferDiscard(string typeName) { await TestInRegularAndScriptAsync( -$@"class C -{{ - void M() - {{ - if (M2(out {typeName} [|x|])) - {{ - }} - }} - - bool M2(out int x) - {{ - x = 0; - return true; - }} -}}", -@"class C -{ - void M() - { - if (M2(out _)) - { - } - } + $$""" + class C + { + void M() + { + if (M2(out {{typeName}} [|x|])) + { + } + } - bool M2(out int x) - { - x = 0; - return true; - } -}", options: PreferDiscard); + bool M2(out int x) + { + x = 0; + return true; + } + } + """, + """ + class C + { + void M() + { + if (M2(out _)) + { + } + } + + bool M2(out int x) + { + x = 0; + return true; + } + } + """, options: PreferDiscard); } [Fact] public async Task UnusedOutVariableDeclaration_MethodOverloads_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - if (M2(out int [|x|])) - { - } - } + """ + class C + { + void M() + { + if (M2(out int [|x|])) + { + } + } - bool M2(out int x) - { - x = 0; - return true; - } + bool M2(out int x) + { + x = 0; + return true; + } - bool M2(out char x) - { - x = 'c'; - return true; - } -}", -@"class C -{ - void M() - { - if (M2(out int _)) - { - } - } + bool M2(out char x) + { + x = 'c'; + return true; + } + } + """, + """ + class C + { + void M() + { + if (M2(out int _)) + { + } + } - bool M2(out int x) - { - x = 0; - return true; - } + bool M2(out int x) + { + x = 0; + return true; + } - bool M2(out char x) - { - x = 'c'; - return true; - } -}", options: PreferDiscard); + bool M2(out char x) + { + x = 'c'; + return true; + } + } + """, options: PreferDiscard); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/31583")] @@ -6981,13 +7645,15 @@ bool M2(out char x) public async Task MissingImports(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - List [|x|] = null; - } -}", optionName); + """ + class C + { + void M() + { + List [|x|] = null; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/31583")] @@ -6996,19 +7662,21 @@ void M() public async Task UsedAssignment_ConditionalPreprocessorDirective(string optionName) { await TestMissingInRegularAndScriptAsync( -@"#define DEBUG + """ + #define DEBUG -class C -{ - int M() - { - int [|x|] = 0; -#if DEBUG - x = 1; -#endif - return x; - } -}", optionName); + class C + { + int M() + { + int [|x|] = 0; + #if DEBUG + x = 1; + #endif + return x; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32855")] @@ -7017,16 +7685,18 @@ int M() public async Task RefLocalInitialization(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class Test -{ - int[] data = { 0 }; + """ + class Test + { + int[] data = { 0 }; - void Method() - { - ref int [|target|] = ref data[0]; - target = 1; - } -}", optionName); + void Method() + { + ref int [|target|] = ref data[0]; + target = 1; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32855")] @@ -7035,17 +7705,19 @@ void Method() public async Task RefLocalAssignment(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class Test -{ - int[] data = { 0 }; - - int Method() - { - ref int target = ref data[0]; - [|target|] = 1; - return data[0]; - } -}", optionName); + """ + class Test + { + int[] data = { 0 }; + + int Method() + { + ref int target = ref data[0]; + [|target|] = 1; + return data[0]; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32903")] @@ -7054,50 +7726,54 @@ int Method() public async Task DelegateCreationWrappedInATuple_UsedInReturnedLambda(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -public class C -{ - private (int, int) createTuple() => (1, 1); + public class C + { + private (int, int) createTuple() => (1, 1); - public (Func, bool) M() - { - var ([|value1, value2|]) = createTuple(); + public (Func, bool) M() + { + var ([|value1, value2|]) = createTuple(); - int LocalFunction() => value1 + value2; + int LocalFunction() => value1 + value2; - return (LocalFunction, true); - } -}", optionName); + return (LocalFunction, true); + } + } + """, optionName); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32923")] public async Task UnusedLocal_ForEach() { await TestDiagnosticsAsync( -@"using System; + """ + using System; -public struct S -{ - public Enumerator GetEnumerator() => throw new NotImplementedException(); + public struct S + { + public Enumerator GetEnumerator() => throw new NotImplementedException(); - public struct Enumerator - { - public Enumerator(S sequence) => throw new NotImplementedException(); - public int Current => throw new NotImplementedException(); - public bool MoveNext() => throw new NotImplementedException(); - } -} + public struct Enumerator + { + public Enumerator(S sequence) => throw new NotImplementedException(); + public int Current => throw new NotImplementedException(); + public bool MoveNext() => throw new NotImplementedException(); + } + } -class C -{ - void M(S s) - { - foreach (var [|x|] in s) - { - } - } -}", new TestParameters(options: PreferDiscard, retainNonFixableDiagnostics: true), + class C + { + void M(S s) + { + foreach (var [|x|] in s) + { + } + } + } + """, new TestParameters(options: PreferDiscard, retainNonFixableDiagnostics: true), Diagnostic("IDE0059")); } @@ -7105,11 +7781,13 @@ void M(S s) public async Task UnusedLocal_ForEach_TopLevelStatement() { await TestMissingInRegularAndScriptAsync( -@"var items = new[] { new { x = 1 } }; + """ + var items = new[] { new { x = 1 } }; -foreach (var [|item|] in items) -{ -}", PreferDiscard, new CSharpParseOptions(LanguageVersion.CSharp9)); + foreach (var [|item|] in items) + { + } + """, PreferDiscard, new CSharpParseOptions(LanguageVersion.CSharp9)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32923")] @@ -7120,29 +7798,31 @@ await TestMissingInRegularAndScriptAsync( public async Task UnusedLocal_SpecialName_01(string variableName, string optionName) { await TestDiagnosticMissingAsync( -$@"using System; + $$""" + using System; -public struct S -{{ - public Enumerator GetEnumerator() => throw new NotImplementedException(); + public struct S + { + public Enumerator GetEnumerator() => throw new NotImplementedException(); - public struct Enumerator - {{ - public Enumerator(S sequence) => throw new NotImplementedException(); - public int Current => throw new NotImplementedException(); - public bool MoveNext() => throw new NotImplementedException(); - }} -}} + public struct Enumerator + { + public Enumerator(S sequence) => throw new NotImplementedException(); + public int Current => throw new NotImplementedException(); + public bool MoveNext() => throw new NotImplementedException(); + } + } -class C -{{ - void M(S s) - {{ - foreach (var [|{variableName}|] in s) - {{ - }} - }} -}}", new TestParameters(options: GetOptions(optionName), retainNonFixableDiagnostics: true)); + class C + { + void M(S s) + { + foreach (var [|{{variableName}}|] in s) + { + } + } + } + """, new TestParameters(options: GetOptions(optionName), retainNonFixableDiagnostics: true)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/32923")] @@ -7153,336 +7833,380 @@ void M(S s) public async Task UnusedLocal_SpecialName_02(string variableName, string optionName) { await TestMissingInRegularAndScriptAsync( -$@"using System; + $$""" + using System; -public class C -{{ - public void M(int p) - {{ - var [|{variableName}|] = p; - }} -}}", optionName); + public class C + { + public void M(int p) + { + var [|{{variableName}}|] = p; + } + } + """, optionName); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32959")] public async Task UsedVariable_BailOutOnSemanticError() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|x|] = 1; - - // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. - Invoke(() => x); + """ + class C + { + void M() + { + int [|x|] = 1; - T Invoke(Func a) { return a(); } - } -}", options: PreferDiscard); + // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. + Invoke(() => x); + + T Invoke(Func a) { return a(); } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32959")] public async Task UnusedVariable_BailOutOnSemanticError() { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M() - { - int [|x|] = 1; - - // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. - Invoke(() => 0); - - T Invoke(Func a) { return a(); } - } -}", options: PreferDiscard); + """ + class C + { + void M() + { + int [|x|] = 1; + + // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type. + Invoke(() => 0); + + T Invoke(Func a) { return a(); } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32946")] public async Task DelegateEscape_01() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action[] M() - { - var [|j|] = 0; - return new Action[1] { () => Console.WriteLine(j) }; - } -}", options: PreferDiscard); + class C + { + Action[] M() + { + var [|j|] = 0; + return new Action[1] { () => Console.WriteLine(j) }; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32946")] public async Task DelegateEscape_02() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action[] M(Action[] actions) - { - var [|j|] = 0; - actions[0] = () => Console.WriteLine(j); - return actions; - } -}", options: PreferDiscard); + class C + { + Action[] M(Action[] actions) + { + var [|j|] = 0; + actions[0] = () => Console.WriteLine(j); + return actions; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32946")] public async Task DelegateEscape_03() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - Action[,] M(Action[,] actions) - { - var [|j|] = 0; - actions[0, 0] = () => Console.WriteLine(j); - return actions; - } -}", options: PreferDiscard); + class C + { + Action[,] M(Action[,] actions) + { + var [|j|] = 0; + actions[0, 0] = () => Console.WriteLine(j); + return actions; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32946")] public async Task DelegateEscape_04() { await TestMissingInRegularAndScriptAsync( -@"using System; -using System.Collections.Generic; + """ + using System; + using System.Collections.Generic; -class C -{ - List M() - { - var [|j|] = 0; - return new List { () => Console.WriteLine(j) }; - } -}", options: PreferDiscard); + class C + { + List M() + { + var [|j|] = 0; + return new List { () => Console.WriteLine(j) }; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32946")] public async Task DelegateEscape_05() { await TestMissingInRegularAndScriptAsync( -@"using System; -using System.Collections.Generic; + """ + using System; + using System.Collections.Generic; -class C -{ - List M() - { - var [|j|] = 0; - var list = new List(); - list.Add(() => Console.WriteLine(j)); - return list; - } -}", options: PreferDiscard); + class C + { + List M() + { + var [|j|] = 0; + var list = new List(); + list.Add(() => Console.WriteLine(j)); + return list; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32924")] public async Task DelegateEscape_06() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - int [|j|] = 0; - Console.CancelKeyPress += (s, e) => e.Cancel = j != 0; - } -}", options: PreferDiscard); + class C + { + void M() + { + int [|j|] = 0; + Console.CancelKeyPress += (s, e) => e.Cancel = j != 0; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32924")] public async Task DelegateEscape_07() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - int [|j|] = 0; - Console.CancelKeyPress += LocalFunctionHandler; - return; + class C + { + void M() + { + int [|j|] = 0; + Console.CancelKeyPress += LocalFunctionHandler; + return; - void LocalFunctionHandler(object s, ConsoleCancelEventArgs e) => e.Cancel = j != 0; - } -}", options: PreferDiscard); + void LocalFunctionHandler(object s, ConsoleCancelEventArgs e) => e.Cancel = j != 0; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32856")] public async Task RedundantAssignment_IfStatementParent() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(int j) - { - if (M2()) - [|j|] = 0; - } + """ + class C + { + void M(int j) + { + if (M2()) + [|j|] = 0; + } - bool M2() => true; -}", -@"class C -{ - void M(int j) - { - if (M2()) - _ = 0; - } + bool M2() => true; + } + """, + """ + class C + { + void M(int j) + { + if (M2()) + _ = 0; + } - bool M2() => true; -}", options: PreferDiscard); + bool M2() => true; + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32856")] public async Task RedundantAssignment_LoopStatementParent() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(int j, int[] array) - { - for (int i = 0; i < array.Length; i++) - [|j|] = i; - } -}", -@"class C -{ - void M(int j, int[] array) - { - for (int i = 0; i < array.Length; i++) - _ = i; - } -}", options: PreferDiscard); + """ + class C + { + void M(int j, int[] array) + { + for (int i = 0; i < array.Length; i++) + [|j|] = i; + } + } + """, + """ + class C + { + void M(int j, int[] array) + { + for (int i = 0; i < array.Length; i++) + _ = i; + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40336")] public async Task RedundantAssignment_ForStatementVariableDeclarationConstant() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - for (int [|i|] = 0; ; ) - { - } - } -}", -@"class C -{ - void M() - { - for (; ; ) - { - } - } -}", options: PreferDiscard); + """ + class C + { + void M() + { + for (int [|i|] = 0; ; ) + { + } + } + } + """, + """ + class C + { + void M() + { + for (; ; ) + { + } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40336")] public async Task RedundantAssignment_ForStatementVariableDeclarationMethod() { await TestInRegularAndScriptAsync( -@"class C -{ - int GetValue() => 0; + """ + class C + { + int GetValue() => 0; - void M() - { - for (int [|i|] = GetValue(); ; ) - { - } - } -}", -@"class C -{ - int GetValue() => 0; + void M() + { + for (int [|i|] = GetValue(); ; ) + { + } + } + } + """, + """ + class C + { + int GetValue() => 0; - void M() - { - for (int _ = GetValue(); ; ) - { - } - } -}", options: PreferDiscard); + void M() + { + for (int _ = GetValue(); ; ) + { + } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40336")] public async Task RedundantAssignment_ForStatementVariableDeclarationStaticMethod() { await TestInRegularAndScriptAsync( -@"class C -{ - static int GetValue() => 0; + """ + class C + { + static int GetValue() => 0; - void M() - { - for (int [|i|] = GetValue(); ; ) - { - } - } -}", -@"class C -{ - static int GetValue() => 0; + void M() + { + for (int [|i|] = GetValue(); ; ) + { + } + } + } + """, + """ + class C + { + static int GetValue() => 0; - void M() - { - for (int _ = GetValue(); ; ) - { - } - } -}", options: PreferDiscard); + void M() + { + for (int _ = GetValue(); ; ) + { + } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40336")] public async Task RedundantAssignment_ForStatementVariableDeclarationInsideUsedLambda() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - Action a = () => - { - for (int [|i|] = 0; ; ) - { - } - }; - a(); - } -}", -@"using System; + class C + { + void M() + { + Action a = () => + { + for (int [|i|] = 0; ; ) + { + } + }; + a(); + } + } + """, + """ + using System; -class C -{ - void M() - { - Action a = () => - { - for (; ; ) - { - } - }; - a(); - } -}", options: PreferDiscard); + class C + { + void M() + { + Action a = () => + { + for (; ; ) + { + } + }; + a(); + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40336")] @@ -7490,249 +8214,275 @@ public async Task RedundantAssignment_ForStatementVariableDeclarationInsideUnuse { //NOTE: Currently the diagnostic is only reported on the outer unused variable a. await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - Action a = () => - { - for (int [|i|] = 0; ; ) - { - } - }; - } -}"); + class C + { + void M() + { + Action a = () => + { + for (int [|i|] = 0; ; ) + { + } + }; + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33299")] public async Task NullCoalesceAssignment_01() { await TestMissingInRegularAndScriptWithAllOptionsAsync( -@"class C -{ - public static void M(C x) - { - [|x|] = M2(); - x ??= new C(); - } + """ + class C + { + public static void M(C x) + { + [|x|] = M2(); + x ??= new C(); + } - private static C M2() => null; -} -", parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + private static C M2() => null; + } + """, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33299")] public async Task NullCoalesceAssignment_02() { await TestMissingInRegularAndScriptWithAllOptionsAsync( -@"class C -{ - public static C M(C x) - { - [|x|] ??= new C(); - return x; - } -} -", parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + public static C M(C x) + { + [|x|] ??= new C(); + return x; + } + } + """, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33299")] public async Task NullCoalesceAssignment_03() { await TestInRegularAndScriptAsync( -@"class C -{ - public static void M(C x) - { - [|x|] ??= new C(); - } -} -", -@"class C -{ - public static void M(C x) - { - _ = x ?? new C(); - } -} -", optionName: nameof(PreferDiscard), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + public static void M(C x) + { + [|x|] ??= new C(); + } + } + """, + """ + class C + { + public static void M(C x) + { + _ = x ?? new C(); + } + } + """, optionName: nameof(PreferDiscard), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33299")] public async Task NullCoalesceAssignment_04() { await TestInRegularAndScriptAsync( -@"class C -{ - public static C M(C x) - { - return [|x|] ??= new C(); - } -} -", -@"class C -{ - public static C M(C x) - { - return x ?? new C(); - } -} -", optionName: nameof(PreferDiscard), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + public static C M(C x) + { + return [|x|] ??= new C(); + } + } + """, + """ + class C + { + public static C M(C x) + { + return x ?? new C(); + } + } + """, optionName: nameof(PreferDiscard), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33299")] public async Task NullCoalesceAssignment_05() { await TestInRegularAndScriptAsync( -@"class C -{ - public static C M(C x) - => [|x|] ??= new C(); -} -", -@"class C -{ - public static C M(C x) - => x ?? new C(); -} -", optionName: nameof(PreferDiscard), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + public static C M(C x) + => [|x|] ??= new C(); + } + """, + """ + class C + { + public static C M(C x) + => x ?? new C(); + } + """, optionName: nameof(PreferDiscard), parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem(32856, "https://github.com/dotnet/roslyn/issues/33312")] public async Task RedundantAssignment_WithLeadingAndTrailingComment() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - // This is a comment before the variable assignment. - // It has two lines. - [|int foo = 0;|] // Trailing comment. - if (true) - { - foo = 1; - } - System.Console.WriteLine(foo); - } -}", -@"class C -{ - void M() - { - // This is a comment before the variable assignment. - // It has two lines. - int foo; - if (true) - { - foo = 1; - } - System.Console.WriteLine(foo); - } -}", options: PreferUnusedLocal); + """ + class C + { + void M() + { + // This is a comment before the variable assignment. + // It has two lines. + [|int foo = 0;|] // Trailing comment. + if (true) + { + foo = 1; + } + System.Console.WriteLine(foo); + } + } + """, + """ + class C + { + void M() + { + // This is a comment before the variable assignment. + // It has two lines. + int foo; + if (true) + { + foo = 1; + } + System.Console.WriteLine(foo); + } + } + """, options: PreferUnusedLocal); } [Fact, WorkItem(32856, "https://github.com/dotnet/roslyn/issues/33312")] public async Task MultipleRedundantAssignment_WithLeadingAndTrailingComment() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - // This is a comment before the variable assignment. - // It has two lines. - {|FixAllInDocument:int unused = 0, foo = 0, bar = 0;|} // Trailing comment. - if (true) - { - foo = 1; - bar = 1; - } - System.Console.WriteLine(foo); - System.Console.WriteLine(bar); - } -}", -@"class C -{ - void M() - { - // This is a comment before the variable assignment. - // It has two lines. - int foo; - int bar; - if (true) - { - foo = 1; - bar = 1; - } - System.Console.WriteLine(foo); - System.Console.WriteLine(bar); - } -}", options: PreferUnusedLocal); + """ + class C + { + void M() + { + // This is a comment before the variable assignment. + // It has two lines. + {|FixAllInDocument:int unused = 0, foo = 0, bar = 0;|} // Trailing comment. + if (true) + { + foo = 1; + bar = 1; + } + System.Console.WriteLine(foo); + System.Console.WriteLine(bar); + } + } + """, + """ + class C + { + void M() + { + // This is a comment before the variable assignment. + // It has two lines. + int foo; + int bar; + if (true) + { + foo = 1; + bar = 1; + } + System.Console.WriteLine(foo); + System.Console.WriteLine(bar); + } + } + """, options: PreferUnusedLocal); } [Fact, WorkItem(32856, "https://github.com/dotnet/roslyn/issues/33312")] public async Task MultipleRedundantAssignment_WithInnerComment() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - {|FixAllInDocument:int unused = 0, /*Comment*/foo = 0, /*Another comment*/ bar = 0;|} - if (true) - { - foo = 1; - } - System.Console.WriteLine(foo); - } -}", -@"class C -{ - void M() - { - int foo; - if (true) - { - foo = 1; - } - System.Console.WriteLine(foo); - } -}", options: PreferUnusedLocal); + """ + class C + { + void M() + { + {|FixAllInDocument:int unused = 0, /*Comment*/foo = 0, /*Another comment*/ bar = 0;|} + if (true) + { + foo = 1; + } + System.Console.WriteLine(foo); + } + } + """, + """ + class C + { + void M() + { + int foo; + if (true) + { + foo = 1; + } + System.Console.WriteLine(foo); + } + } + """, options: PreferUnusedLocal); } [Fact, WorkItem(32856, "https://github.com/dotnet/roslyn/issues/33312")] public async Task DeclarationPatternInSwitchCase_WithTrivia_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - switch (p) - { - case /*Inline trivia*/ int [|x|]: - // Other trivia - x = 1; - break; - }; - } -}", -@"class C -{ - void M(object p) - { - switch (p) - { - case /*Inline trivia*/ int _: - // Other trivia - int x = 1; - break; - }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + void M(object p) + { + switch (p) + { + case /*Inline trivia*/ int [|x|]: + // Other trivia + x = 1; + break; + }; + } + } + """, + """ + class C + { + void M(object p) + { + switch (p) + { + case /*Inline trivia*/ int _: + // Other trivia + int x = 1; + break; + }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Theory, WorkItem(32856, "https://github.com/dotnet/roslyn/issues/33312")] @@ -7741,19 +8491,21 @@ public async Task DeclarationPatternInSwitchCase_WithTrivia_PreferUnusedLocal( [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestMissingInRegularAndScriptAsync( -@"class C -{ - void M(object p) - { - switch (p) - { - case /*Inline trivia*/ int [|x|]: - // Other trivia - x = 1; - break; - }; - } -}", PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion)); + """ + class C + { + void M(object p) + { + switch (p) + { + case /*Inline trivia*/ int [|x|]: + // Other trivia + x = 1; + break; + }; + } + } + """, PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion)); } [Theory, WorkItem(32856, "https://github.com/dotnet/roslyn/issues/33312")] @@ -7762,23 +8514,26 @@ public async Task DeclarationPatternInSwitchCase_WithTrivia_TypePattern( [CombinatorialValues(CodeFixTestBehaviors.None, CodeFixTestBehaviors.FixOne)] CodeFixTestBehaviors testBehaviors) { var source = -@"class C -{ - void M(object p) - { - switch (p) - { - case /*Inline trivia*/ int {|IDE0059:x|}: - // Other trivia - {|IDE0059:x|} = 1; - break; - }; - } -}"; + """ + class C + { + void M(object p) + { + switch (p) + { + case /*Inline trivia*/ int {|IDE0059:x|}: + // Other trivia + {|IDE0059:x|} = 1; + break; + }; + } + } + """; var (fixedSource, iterations) = testBehaviors switch { CodeFixTestBehaviors.None => -(@"class C +(""" +class C { void M(object p) { @@ -7789,9 +8544,11 @@ void M(object p) break; }; } -}", iterations: 2), +} +""", iterations: 2), CodeFixTestBehaviors.FixOne => -(@"class C +(""" +class C { void M(object p) { @@ -7803,7 +8560,8 @@ void M(object p) break; }; } -}", iterations: 1), +} +""", iterations: 1), _ => throw ExceptionUtilities.Unreachable(), }; @@ -7828,19 +8586,21 @@ void M(object p) public async Task UsedInArgumentAfterAnArgumentWithControlFlow(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class A -{ - public static void M(int? x) - { - A [|a|] = new A(); - a = M2(x ?? 1, a); - } + """ + class A + { + public static void M(int? x) + { + A [|a|] = new A(); + a = M2(x ?? 1, a); + } - private static A M2(int? x, A a) - { - return a; - } -}", optionName); + private static A M2(int? x, A a) + { + return a; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33949")] @@ -7849,16 +8609,18 @@ private static A M2(int? x, A a) public async Task CompoundAssignmentWithControlFlowInValue(string optionName) { await TestMissingInRegularAndScriptAsync( -@"class A -{ - public static void M(int? x) - { - int [|a|] = 1; - a += M2(x ?? 1); - } + """ + class A + { + public static void M(int? x) + { + int [|a|] = 1; + a += M2(x ?? 1); + } - private static int M2(int? x) => 0; -}", optionName); + private static int M2(int? x) => 0; + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33843")] @@ -7867,20 +8629,22 @@ public static void M(int? x) public async Task UsedValueWithUsingStatementAndLocalFunction(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - private class Disposable : IDisposable { public void Dispose() { } } - public int M() - { - var result = 0; - void append() => [|result|] += 1; // IDE0059 for 'result' - using (var a = new Disposable()) - append(); - return result; - } -}", optionName); + class C + { + private class Disposable : IDisposable { public void Dispose() { } } + public int M() + { + var result = 0; + void append() => [|result|] += 1; // IDE0059 for 'result' + using (var a = new Disposable()) + append(); + return result; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33843")] @@ -7889,20 +8653,22 @@ public int M() public async Task UsedValueWithUsingStatementAndLambda(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - private class Disposable : IDisposable { public void Dispose() { } } - public int M() - { - var result = 0; - Action append = () => [|result|] += 1; // IDE0059 for 'result' - using (var a = new Disposable()) - append(); - return result; - } -}", optionName); + class C + { + private class Disposable : IDisposable { public void Dispose() { } } + public int M() + { + var result = 0; + Action append = () => [|result|] += 1; // IDE0059 for 'result' + using (var a = new Disposable()) + append(); + return result; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33843")] @@ -7911,22 +8677,24 @@ public int M() public async Task UsedValueWithUsingStatementAndLambda_02(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - private class Disposable : IDisposable { public void Dispose() { } } - public int M() - { - var result = 0; - Action appendLambda = () => [|result|] += 1; - void appendLocalFunction() => appendLambda(); - Action appendDelegate = appendLocalFunction; - using (var a = new Disposable()) - appendDelegate(); - return result; - } -}", optionName); + class C + { + private class Disposable : IDisposable { public void Dispose() { } } + public int M() + { + var result = 0; + Action appendLambda = () => [|result|] += 1; + void appendLocalFunction() => appendLambda(); + Action appendDelegate = appendLocalFunction; + using (var a = new Disposable()) + appendDelegate(); + return result; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33843")] @@ -7935,22 +8703,24 @@ public int M() public async Task UsedValueWithUsingStatementAndLambda_03(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - private class Disposable : IDisposable { public void Dispose() { } } - public int M() - { - var result = 0; - void appendLocalFunction() => [|result|] += 1; - Action appendLambda = () => appendLocalFunction(); - Action appendDelegate = appendLambda; - using (var a = new Disposable()) - appendDelegate(); - return result; - } -}", optionName); + class C + { + private class Disposable : IDisposable { public void Dispose() { } } + public int M() + { + var result = 0; + void appendLocalFunction() => [|result|] += 1; + Action appendLambda = () => appendLocalFunction(); + Action appendDelegate = appendLambda; + using (var a = new Disposable()) + appendDelegate(); + return result; + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33937")] @@ -7959,31 +8729,33 @@ public int M() public async Task AssignedInCatchUsedInFinally_ThrowInCatch(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -public static class Program -{ - public static void Test() - { - var exceptionThrown = false; - try - { - throw new Exception(); - } - catch - { - // The `exceptionThrown` token is incorrectly greyed out in the IDE - // IDE0059 Value assigned to 'exceptionThrown' is never used - [|exceptionThrown|] = true; - throw; - } - finally - { - // Breakpoint on this line is hit and 'true' is printed - Console.WriteLine(exceptionThrown); - } - } -}", optionName); + public static class Program + { + public static void Test() + { + var exceptionThrown = false; + try + { + throw new Exception(); + } + catch + { + // The `exceptionThrown` token is incorrectly greyed out in the IDE + // IDE0059 Value assigned to 'exceptionThrown' is never used + [|exceptionThrown|] = true; + throw; + } + finally + { + // Breakpoint on this line is hit and 'true' is printed + Console.WriteLine(exceptionThrown); + } + } + } + """, optionName); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/33937")] @@ -7992,182 +8764,198 @@ public static void Test() public async Task AssignedInCatchUsedInFinally_NoThrowInCatch(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -public static class Program -{ - public static void Test() - { - var exceptionThrown = false; - try - { - throw new Exception(); - } - catch - { - [|exceptionThrown|] = true; - } - finally - { - Console.WriteLine(exceptionThrown); - } - } -}", optionName); + public static class Program + { + public static void Test() + { + var exceptionThrown = false; + try + { + throw new Exception(); + } + catch + { + [|exceptionThrown|] = true; + } + finally + { + Console.WriteLine(exceptionThrown); + } + } + } + """, optionName); } [Fact] public async Task DoesNotUseLocalFunctionName_PreferUnused() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int [|x|] = M2(); - x = 2; - return x; + """ + class C + { + int M() + { + int [|x|] = M2(); + x = 2; + return x; - void unused() { } - } + void unused() { } + } - int M2() => 0; -}", -@"class C -{ - int M() - { - int unused1 = M2(); - int x = 2; - return x; + int M2() => 0; + } + """, + """ + class C + { + int M() + { + int unused1 = M2(); + int x = 2; + return x; - void unused() { } - } + void unused() { } + } - int M2() => 0; -}", options: PreferUnusedLocal); + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task CanUseLocalFunctionParameterName_PreferUnused() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - int [|x|] = M2(); - x = 2; - return x; + """ + class C + { + int M() + { + int [|x|] = M2(); + x = 2; + return x; - void MLocal(int unused) { } - } + void MLocal(int unused) { } + } - int M2() => 0; -}", -@"class C -{ - int M() - { - int unused = M2(); - int x = 2; - return x; + int M2() => 0; + } + """, + """ + class C + { + int M() + { + int unused = M2(); + int x = 2; + return x; - void MLocal(int unused) { } - } + void MLocal(int unused) { } + } - int M2() => 0; -}", options: PreferUnusedLocal); + int M2() => 0; + } + """, options: PreferUnusedLocal); } [Fact] public async Task DoesNotUseLambdaFunctionParameterNameWithCSharpLessThan8_PreferUnused() { await TestInRegularAndScriptAsync( -@" -using System; -class C -{ - int M() - { - int [|x|] = M2(); - x = 2; - Action myLambda = unused => { }; + """ + using System; + class C + { + int M() + { + int [|x|] = M2(); + x = 2; + Action myLambda = unused => { }; - return x; - } + return x; + } - int M2() => 0; -}", -@" -using System; -class C -{ - int M() - { - int unused1 = M2(); - int x = 2; - Action myLambda = unused => { }; + int M2() => 0; + } + """, + """ + using System; + class C + { + int M() + { + int unused1 = M2(); + int x = 2; + Action myLambda = unused => { }; - return x; - } + return x; + } - int M2() => 0; -}", options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3)); + int M2() => 0; + } + """, options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_3)); } [Fact] public async Task CanUseLambdaFunctionParameterNameWithCSharp8_PreferUnused() { await TestInRegularAndScriptAsync( -@" -using System; -class C -{ - int M() - { - int [|x|] = M2(); - x = 2; - Action myLambda = unused => { }; + """ + using System; + class C + { + int M() + { + int [|x|] = M2(); + x = 2; + Action myLambda = unused => { }; - return x; - } + return x; + } - int M2() => 0; -}", -@" -using System; -class C -{ - int M() - { - int unused = M2(); - int x = 2; - Action myLambda = unused => { }; + int M2() => 0; + } + """, + """ + using System; + class C + { + int M() + { + int unused = M2(); + int x = 2; + Action myLambda = unused => { }; - return x; - } + return x; + } - int M2() => 0; -}", options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + int M2() => 0; + } + """, options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33464")] public async Task UsingDeclaration() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C : IDisposable -{ - public void Dispose() - { - } + class C : IDisposable + { + public void Dispose() + { + } - void M() - { - using var [|x|] = new C(); - } -}", options: PreferDiscard, + void M() + { + using var [|x|] = new C(); + } + } + """, options: PreferDiscard, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9)); } @@ -8175,20 +8963,22 @@ void M() public async Task UsingDeclarationWithInitializer() { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C : IDisposable -{ - public int P { get; set; } - public void Dispose() - { - } + class C : IDisposable + { + public int P { get; set; } + public void Dispose() + { + } - void M() - { - using var [|x|] = new C() { P = 1 }; - } -}", options: PreferDiscard, + void M() + { + using var [|x|] = new C() { P = 1 }; + } + } + """, options: PreferDiscard, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9)); } @@ -8196,145 +8986,157 @@ void M() public async Task RefParameter_WrittenBeforeThrow() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - public void DoSomething(ref bool p) - { - if (p) - { - [|p|] = false; - throw new ArgumentException(string.Empty); - } - } -}"); + class C + { + public void DoSomething(ref bool p) + { + if (p) + { + [|p|] = false; + throw new ArgumentException(string.Empty); + } + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37709")] public async Task OutParameter_WrittenBeforeThrow() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - public void DoSomething(out bool p, bool x) - { - if (x) - { - [|p|] = false; - throw new ArgumentException(string.Empty); - } - else - { - p = true; - } - } -}"); + class C + { + public void DoSomething(out bool p, bool x) + { + if (x) + { + [|p|] = false; + throw new ArgumentException(string.Empty); + } + else + { + p = true; + } + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37871")] public async Task RefParameter_RefAssignmentFollowedByAssignment() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - delegate ref int UnsafeAdd(ref int source, int elementOffset); - static UnsafeAdd MyUnsafeAdd; - - static void T1(ref int param) - { - [|param|] = ref MyUnsafeAdd(ref param, 1); - param = default; - } -}"); + class C + { + delegate ref int UnsafeAdd(ref int source, int elementOffset); + static UnsafeAdd MyUnsafeAdd; + + static void T1(ref int param) + { + [|param|] = ref MyUnsafeAdd(ref param, 1); + param = default; + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37871")] public async Task RefParameter_RefConditionalAssignment() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - delegate ref int UnsafeAdd(ref int source, int elementOffset); - static UnsafeAdd MyUnsafeAdd; + class C + { + delegate ref int UnsafeAdd(ref int source, int elementOffset); + static UnsafeAdd MyUnsafeAdd; - static void T1(ref int param, bool flag) - { - [|param|] = flag ? ref MyUnsafeAdd(ref param, 1) : ref MyUnsafeAdd(ref param, 2); - param = default; - } -}"); + static void T1(ref int param, bool flag) + { + [|param|] = flag ? ref MyUnsafeAdd(ref param, 1) : ref MyUnsafeAdd(ref param, 2); + param = default; + } + } + """); } [Fact] public async Task LocalFunction_OutParameter_UsedInCaller() { await TestDiagnosticMissingAsync( -@" -public class C -{ - public void M() - { - if (GetVal(out var [|value|])) - { - var x = value; - } + """ + public class C + { + public void M() + { + if (GetVal(out var [|value|])) + { + var x = value; + } - bool GetVal(out string val) - { - val = string.Empty; - return true; - } - } -}"); + bool GetVal(out string val) + { + val = string.Empty; + return true; + } + } + } + """); } [Fact] public async Task TupleMember_UsedAfterContinueBranch() { await TestDiagnosticMissingAsync( -@" -using System; -using System.Collections.Generic; + """ + using System; + using System.Collections.Generic; -public class Test -{ - void M(List<(int, int)> list) - { - foreach (var (x, [|y|]) in list) - { - if (x != 0) - { - continue; - } + public class Test + { + void M(List<(int, int)> list) + { + foreach (var (x, [|y|]) in list) + { + if (x != 0) + { + continue; + } - Console.Write(y); - } - } -}"); + Console.Write(y); + } + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38640")] public async Task DeclarationPatternInSwitchExpressionArm_UsedLocal() { await TestDiagnosticMissingAsync( -@"class C -{ - string M(object obj) - { - return obj switch - { - int [|p2|] => p2.ToString(), - _ => ""NoMatch"" - }; - } -}", new TestParameters(options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8))); + """ + class C + { + string M(object obj) + { + return obj switch + { + int [|p2|] => p2.ToString(), + _ => "NoMatch" + }; + } + } + """, new TestParameters(options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8))); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/38640")] @@ -8343,79 +9145,91 @@ public async Task DeclarationPatternInSwitchExpressionArm_UnusedLocal_PreferUnus [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestDiagnosticMissingAsync( -@"class C -{ - string M(object obj) - { - return obj switch - { - int [|p2|] => ""Int"", - _ => ""NoMatch"" - }; - } -}", new TestParameters(options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion))); + """ + class C + { + string M(object obj) + { + return obj switch + { + int [|p2|] => "Int", + _ => "NoMatch" + }; + } + } + """, new TestParameters(options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion))); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40499")] public async Task LocalUsedWithPropertySubPattern() { await TestDiagnosticMissingAsync( -@"class C -{ - public object P { get; } - void M() - { - C [|c|] = new C(); - var x = c is { P : int i }; - } -}", new TestParameters(options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8))); + """ + class C + { + public object P { get; } + void M() + { + C [|c|] = new C(); + var x = c is { P : int i }; + } + } + """, new TestParameters(options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8))); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40499")] public async Task UnusedLocalDefinedInPropertySubPattern_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - public object P { get; } - void M(C c) - { - var x = c is { P : int [|i|] }; - } -}", -@"class C -{ - public object P { get; } - void M(C c) - { - var x = c is { P : int _ }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + public object P { get; } + void M(C c) + { + var x = c is { P : int [|i|] }; + } + } + """, + """ + class C + { + public object P { get; } + void M(C c) + { + var x = c is { P : int _ }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40499")] public async Task UnusedLocalDefinedInPropertySubPattern_TypePattern() { var source = -@"class C -{ - public object P { get; } - bool M(C c) - { - var x = c is { P : int {|IDE0059:i|} }; - return x; - } -}"; + """ + class C + { + public object P { get; } + bool M(C c) + { + var x = c is { P : int {|IDE0059:i|} }; + return x; + } + } + """; var fixedSource = -@"class C -{ - public object P { get; } - bool M(C c) - { - var x = c is { P : int }; - return x; - } -}"; + """ + class C + { + public object P { get; } + bool M(C c) + { + var x = c is { P : int }; + return x; + } + } + """; await new VerifyCS.Test { @@ -8435,22 +9249,26 @@ public async Task UnusedVarLocalDefinedInPropertySubPattern_PreferDiscard( [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestInRegularAndScriptAsync( -@"class C -{ - public object P { get; } - void M(C c) - { - var x = c is { P : var [|i|] }; - } -}", -@"class C -{ - public object P { get; } - void M(C c) - { - var x = c is { P : _ }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(languageVersion)); + """ + class C + { + public object P { get; } + void M(C c) + { + var x = c is { P : var [|i|] }; + } + } + """, + """ + class C + { + public object P { get; } + void M(C c) + { + var x = c is { P : _ }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(languageVersion)); } [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/40499")] @@ -8459,71 +9277,81 @@ public async Task UnusedLocalDefinedInPropertySubPattern_PreferUnusedLocal( [CombinatorialValues(LanguageVersion.CSharp8, LanguageVersion.CSharp9)] LanguageVersion languageVersion) { await TestDiagnosticMissingAsync( -@"class C -{ - public object P { get; } - void M(C c) - { - var x = c is { P : int [|i|] }; - } -}", new TestParameters(options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion))); + """ + class C + { + public object P { get; } + void M(C c) + { + var x = c is { P : int [|i|] }; + } + } + """, new TestParameters(options: PreferUnusedLocal, parseOptions: new CSharpParseOptions(languageVersion))); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38640")] public async Task DeclarationPatternInSwitchExpressionArm_UnusedLocal_PreferDiscard() { await TestInRegularAndScriptAsync( -@"class C -{ - string M(object obj) - { - return obj switch - { - int [|p2|] => ""Int"", - _ => ""NoMatch"" - }; - } -}", -@"class C -{ - string M(object obj) - { - return obj switch - { - int _ => ""Int"", - _ => ""NoMatch"" - }; - } -}", options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); + """ + class C + { + string M(object obj) + { + return obj switch + { + int [|p2|] => "Int", + _ => "NoMatch" + }; + } + } + """, + """ + class C + { + string M(object obj) + { + return obj switch + { + int _ => "Int", + _ => "NoMatch" + }; + } + } + """, options: PreferDiscard, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38640")] public async Task DeclarationPatternInSwitchExpressionArm_UnusedLocal_TypePattern() { var source = -@"class C -{ - string M(object obj) - { - return obj switch - { - int {|IDE0059:p2|} => ""Int"", - _ => ""NoMatch"" - }; - } -}"; + """ + class C + { + string M(object obj) + { + return obj switch + { + int {|IDE0059:p2|} => "Int", + _ => "NoMatch" + }; + } + } + """; var fixedSource = -@"class C -{ - string M(object obj) - { - return obj switch - { - int => ""Int"", - _ => ""NoMatch"" - }; - } -}"; + """ + class C + { + string M(object obj) + { + return obj switch + { + int => "Int", + _ => "NoMatch" + }; + } + } + """; await new VerifyCS.Test { @@ -8541,205 +9369,215 @@ string M(object obj) public async Task AssignmentInTry_UsedInFinally_NoDiagnostic() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - void M(int i) - { - bool b = false; - try - { - if (i == 0) - { - [|b|] = true; - } - } - finally - { - if (!b) - { - Console.WriteLine(i); - } - } - } -}"); + class C + { + void M(int i) + { + bool b = false; + try + { + if (i == 0) + { + [|b|] = true; + } + } + finally + { + if (!b) + { + Console.WriteLine(i); + } + } + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39755")] public async Task AssignmentInTry_UsedInFinally_NoDiagnostic_02() { await TestDiagnosticMissingAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - IntPtr a = (IntPtr)1; - try - { - var b = a; + class C + { + void M() + { + IntPtr a = (IntPtr)1; + try + { + var b = a; - if (Some(a)) - [|a|] = IntPtr.Zero; - } - finally - { - if (a != IntPtr.Zero) - { + if (Some(a)) + [|a|] = IntPtr.Zero; + } + finally + { + if (a != IntPtr.Zero) + { - } - } - } + } + } + } - bool Some(IntPtr a) => true; -}"); + bool Some(IntPtr a) => true; + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39755")] public async Task AssignmentInTry_NotUsedInFinally_Diagnostic() { await TestInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M(int i) - { - bool b = false; - try - { - if (i == 0) - { - [|b|] = true; - } - } - finally - { - } - } -}", -@"using System; + class C + { + void M(int i) + { + bool b = false; + try + { + if (i == 0) + { + [|b|] = true; + } + } + finally + { + } + } + } + """, + """ + using System; -class C -{ - void M(int i) - { - bool b = false; - try - { - if (i == 0) - { - } - } - finally - { - } - } -}", options: PreferDiscard); + class C + { + void M(int i) + { + bool b = false; + try + { + if (i == 0) + { + } + } + finally + { + } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38507")] public async Task TestCodeFixTitleForBlockBodyRedundantCompoundAssignmentReturn() { - var source = @" -class C -{ - C M(C x) - { - return [|x ??= M2()|]; - } + var source = """ + class C + { + C M(C x) + { + return [|x ??= M2()|]; + } - C M2() => new C(); -} -"; + C M2() => new C(); + } + """; - await TestExactActionSetOfferedAsync(source, new[] { CodeFixesResources.Remove_redundant_assignment }); + await TestExactActionSetOfferedAsync(source, [CodeFixesResources.Remove_redundant_assignment]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38507")] public async Task TestCodeFixTitleForExpressionBodyRedundantCompoundAssignmentReturn() { - var source = @" -class C -{ - C M(C x) => [|x ??= M2()|]; + var source = """ + class C + { + C M(C x) => [|x ??= M2()|]; - C M2() => new C(); -} -"; - await TestExactActionSetOfferedAsync(source, new[] { CodeFixesResources.Remove_redundant_assignment }); + C M2() => new C(); + } + """; + await TestExactActionSetOfferedAsync(source, [CodeFixesResources.Remove_redundant_assignment]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38507")] public async Task TestCodeFixTitleForPatternMatching() { - var source = @" -class C -{ - void M() - { - var c = M2(); - if [|(c is object obj)|] - { - } - } + var source = """ + class C + { + void M() + { + var c = M2(); + if [|(c is object obj)|] + { + } + } - C M2() => new C(); -} -"; + C M2() => new C(); + } + """; - await TestExactActionSetOfferedAsync(source, new[] { CodeFixesResources.Remove_redundant_assignment }); + await TestExactActionSetOfferedAsync(source, [CodeFixesResources.Remove_redundant_assignment]); } [Fact, WorkItem(38507, "https://github.com/dotnet/roslyn/issues/46251")] public async Task TestCodeFixForAllInDocumentForNestedDiagnostic() { - var source = @" -using System; -namespace ConsoleApp -{ - public static class ConsoleApp - { - public static void Main(string[] args) - { - {|FixAllInDocument:Foo(() => { Bar(); return true; })|}; - } + var source = """ + using System; + namespace ConsoleApp + { + public static class ConsoleApp + { + public static void Main(string[] args) + { + {|FixAllInDocument:Foo(() => { Bar(); return true; })|}; + } - public static bool Foo(Func func) - { - return func. Invoke(); - } + public static bool Foo(Func func) + { + return func. Invoke(); + } - public static bool Bar() - { - return true; - } - } -}"; - var expected = @" -using System; -namespace ConsoleApp -{ - public static class ConsoleApp - { - public static void Main(string[] args) - { - _ = Foo(() => { _ = Bar(); return true; }); - } + public static bool Bar() + { + return true; + } + } + } + """; + var expected = """ + using System; + namespace ConsoleApp + { + public static class ConsoleApp + { + public static void Main(string[] args) + { + _ = Foo(() => { _ = Bar(); return true; }); + } - public static bool Foo(Func func) - { - return func. Invoke(); - } + public static bool Foo(Func func) + { + return func. Invoke(); + } - public static bool Bar() - { - return true; - } - } -}"; + public static bool Bar() + { + return true; + } + } + } + """; await TestInRegularAndScriptAsync(source, expected, options: PreferDiscard).ConfigureAwait(false); } @@ -8747,80 +9585,92 @@ public static bool Bar() public async Task UnusedVarPattern_PartOfCase() { await TestInRegularAndScriptAsync( -@"static class Program -{ - public static void Main() - { - switch (string.Empty.Length) - { - case var [|i|] when string.Empty.Length switch { var y => y > 0 }: - { - break; - } - } - } -}", -@"static class Program -{ - public static void Main() - { - switch (string.Empty.Length) - { - case var _ when string.Empty.Length switch { var y => y > 0 }: - { - break; - } - } - } -}", options: PreferDiscard); + """ + static class Program + { + public static void Main() + { + switch (string.Empty.Length) + { + case var [|i|] when string.Empty.Length switch { var y => y > 0 }: + { + break; + } + } + } + } + """, + """ + static class Program + { + public static void Main() + { + switch (string.Empty.Length) + { + case var _ when string.Empty.Length switch { var y => y > 0 }: + { + break; + } + } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45768")] public async Task UnusedVarPattern_PartOfIs() { await TestInRegularAndScriptAsync( -@"static class Program -{ - public static void Main() - { - if (string.Empty.Length is var [|x|]) - { - } - } -}", -@"static class Program -{ - public static void Main() - { - if (string.Empty.Length is var _) - { - } - } -}", options: PreferDiscard); + """ + static class Program + { + public static void Main() + { + if (string.Empty.Length is var [|x|]) + { + } + } + } + """, + """ + static class Program + { + public static void Main() + { + if (string.Empty.Length is var _) + { + } + } + } + """, options: PreferDiscard); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45768")] public async Task UnusedVarPattern_TestTrivia() { await TestInRegularAndScriptAsync( -@"static class Program -{ - public static void Main() - { - if (string.Empty.Length is var [|/*1*/x/*2*/|]) - { - } - } -}", -@"static class Program -{ - public static void Main() - { - if (string.Empty.Length is var /*1*/_/*2*/) - { - } - } -}", options: PreferDiscard); + """ + static class Program + { + public static void Main() + { + if (string.Empty.Length is var [|/*1*/x/*2*/|]) + { + } + } + } + """, + """ + static class Program + { + public static void Main() + { + if (string.Empty.Length is var /*1*/_/*2*/) + { + } + } + } + """, options: PreferDiscard); } [WorkItem("https://github.com/dotnet/roslyn/issues/57650")] @@ -8830,42 +9680,47 @@ public static void Main() public async Task UseInLambda_WithInvocationOutsideLocalScope(string optionName) { await TestMissingInRegularAndScriptAsync( -@"using System; + """ + using System; -class C -{ - void M() - { - Action act = null; - { - var[| capture |] = new object(); - act = () => capture.ToString(); - } - act(); - } -}", optionName); + class C + { + void M() + { + Action act = null; + { + var[| capture |] = new object(); + act = () => capture.ToString(); + } + act(); + } + } + """, optionName); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/64291")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/64291")] public async Task TestImplicitObjectCreationInInitialization() { var source = -@"class C -{ - void M() - { - C {|IDE0059:c|} = new(); - } -}"; + """ + class C + { + void M() + { + C {|IDE0059:c|} = new(); + } + } + """; var fixedSource = -@"class C -{ - void M() - { - _ = new C(); - } -}"; + """ + class C + { + void M() + { + _ = new C(); + } + } + """; await new VerifyCS.Test { @@ -8883,23 +9738,27 @@ void M() public async Task TestImplicitObjectCreationInAssignment() { var source = -@"class C -{ - void M(C c) - { - System.Console.WriteLine(c); - {|IDE0059:c|} = new(); - } -}"; + """ + class C + { + void M(C c) + { + System.Console.WriteLine(c); + {|IDE0059:c|} = new(); + } + } + """; var fixedSource = -@"class C -{ - void M(C c) - { - System.Console.WriteLine(c); - _ = new C(); - } -}"; + """ + class C + { + void M(C c) + { + System.Console.WriteLine(c); + _ = new C(); + } + } + """; await new VerifyCS.Test { diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueExpressionStatementTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueExpressionStatementTests.cs index 560fdfcaa27b7..21900f86a38b5 100644 --- a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueExpressionStatementTests.cs +++ b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueExpressionStatementTests.cs @@ -119,15 +119,17 @@ void M() int M2() => 0; } """, -$@"class C -{{ - void M() - {{ - {fix} = M2(); - }} - - int M2() => 0; -}}", optionName); + $$""" + class C + { + void M() + { + {{fix}} = M2(); + } + + int M2() => 0; + } + """, optionName); } [Theory] @@ -147,15 +149,17 @@ void M() C M2() => new C(); } """, -$@"class C -{{ - void M() - {{ - {fix} = M2(); - }} - - C M2() => new C(); -}}", optionName); + $$""" + class C + { + void M() + { + {{fix}} = M2(); + } + + C M2() => new C(); + } + """, optionName); } [Theory] @@ -295,15 +299,17 @@ void M2() { } public async Task ExpressionStatement_AssignmentExpression(string op) { await TestMissingInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - void M(int x) - {{ - x {op} [|M2()|]; - }} - - int M2() => 0; -}}"); + $$""" + class C + { + void M(int x) + { + x {{op}} [|M2()|]; + } + + int M2() => 0; + } + """); } [Theory] @@ -314,14 +320,16 @@ void M(int x) public async Task ExpressionStatement_IncrementOrDecrement(string incrementOrDecrement) { await TestMissingInRegularAndScriptWithAllOptionsAsync( -$@"class C -{{ - int M(int x) - {{ - [|{incrementOrDecrement}|]; - return x; - }} -}}"); + $$""" + class C + { + int M(int x) + { + [|{{incrementOrDecrement}}|]; + return x; + } + } + """); } [Fact] @@ -487,23 +495,25 @@ void M(int unused1, int unused2) int M2() => 0; } """, -$@"class C -{{ - public C() - {{ - {fix1} = M2(); // Separate code block - }} - - void M(int unused1, int unused2) - {{ - {fix3} = M2(); - {fix2} = M2(); // Another instance in same code block - _ = M2(); // Already fixed - var x = M2(); // Different unused value diagnostic - }} - - int M2() => 0; -}}", optionName); + $$""" + class C + { + public C() + { + {{fix1}} = M2(); // Separate code block + } + + void M(int unused1, int unused2) + { + {{fix3}} = M2(); + {{fix2}} = M2(); // Another instance in same code block + _ = M2(); // Already fixed + var x = M2(); // Different unused value diagnostic + } + + int M2() => 0; + } + """, optionName); } [Fact] diff --git a/src/Analyzers/CSharp/Tests/ReplaceDefaultLiteral/ReplaceDefaultLiteralTests.cs b/src/Analyzers/CSharp/Tests/ReplaceDefaultLiteral/ReplaceDefaultLiteralTests.cs index f2e0da0bf582d..383e1670779f6 100644 --- a/src/Analyzers/CSharp/Tests/ReplaceDefaultLiteral/ReplaceDefaultLiteralTests.cs +++ b/src/Analyzers/CSharp/Tests/ReplaceDefaultLiteral/ReplaceDefaultLiteralTests.cs @@ -211,13 +211,15 @@ void M() public async Task TestCSharp7_1_InCaseSwitchLabel_NotForInvalidType(string expression) { await TestMissingWithLanguageVersionsAsync( -$@"class C -{{ - void M() - {{ - switch ({expression}) {{ case [||]default: }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M() + { + switch ({{expression}}) { case [||]default: } + } + } + """, s_csharp7_1above); } [Fact] @@ -372,13 +374,15 @@ void M() public async Task TestCSharp7_1_InCasePatternSwitchLabel_NotForInvalidType(string expression) { await TestMissingWithLanguageVersionsAsync( -$@"class C -{{ - void M() - {{ - switch ({expression}) {{ case [||]default when true: }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M() + { + switch ({{expression}}) { case [||]default when true: } + } + } + """, s_csharp7_1above); } [Fact] @@ -492,20 +496,24 @@ void M() public async Task TestCSharp7_1_InIsPattern_BuiltInType(string type, string expectedLiteral) { await TestWithLanguageVersionsAsync( -$@"class C -{{ - void M({type} value) - {{ - if (value is [||]default) {{ }} - }} -}}", -$@"class C -{{ - void M({type} value) - {{ - if (value is {expectedLiteral}) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M({{type}} value) + { + if (value is [||]default) { } + } + } + """, + $$""" + class C + { + void M({{type}} value) + { + if (value is {{expectedLiteral}}) { } + } + } + """, s_csharp7_1above); } [Fact] @@ -565,22 +573,26 @@ void M() public async Task TestCSharp7_1_InIsPattern_CustomReferenceType(string typeDeclaration) { await TestWithLanguageVersionsAsync( -$@"class C -{{ - {typeDeclaration} - void M() - {{ - if (new Type() is [||]default) {{ }} - }} -}}", -$@"class C -{{ - {typeDeclaration} - void M() - {{ - if (new Type() is null) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + {{typeDeclaration}} + void M() + { + if (new Type() is [||]default) { } + } + } + """, + $$""" + class C + { + {{typeDeclaration}} + void M() + { + if (new Type() is null) { } + } + } + """, s_csharp7_1above); } [Theory] @@ -593,22 +605,26 @@ void M() public async Task TestCSharp7_1_InIsPattern_CustomEnum_WithoutSpecialMember(string enumDeclaration) { await TestWithLanguageVersionsAsync( -$@"class C -{{ - {enumDeclaration} - void M() - {{ - if (new Enum() is [||]default) {{ }} - }} -}}", -$@"class C -{{ - {enumDeclaration} - void M() - {{ - if (new Enum() is 0) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + {{enumDeclaration}} + void M() + { + if (new Enum() is [||]default) { } + } + } + """, + $$""" + class C + { + {{enumDeclaration}} + void M() + { + if (new Enum() is 0) { } + } + } + """, s_csharp7_1above); } [Theory] @@ -626,22 +642,26 @@ void M() public async Task TestCSharp7_1_InIsPattern_CustomEnum_WithSpecialMember(string enumDeclaration) { await TestWithLanguageVersionsAsync( -$@"class C -{{ - {enumDeclaration} - void M() - {{ - if (new Enum() is [||]default) {{ }} - }} -}}", -$@"class C -{{ - {enumDeclaration} - void M() - {{ - if (new Enum() is Enum.None) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + {{enumDeclaration}} + void M() + { + if (new Enum() is [||]default) { } + } + } + """, + $$""" + class C + { + {{enumDeclaration}} + void M() + { + if (new Enum() is Enum.None) { } + } + } + """, s_csharp7_1above); } [Fact] @@ -702,24 +722,28 @@ void M() public async Task TestCSharp7_1_InIsPattern_CustomReferenceTypeOfAnonymousType(string typeDeclaration) { await TestWithLanguageVersionsAsync( -$@"class C -{{ - {typeDeclaration} - Container ToContainer(T value) => new Container(); - void M() - {{ - if (ToContainer(new {{ x = 0 }}) is [||]default) {{ }} - }} -}}", -$@"class C -{{ - {typeDeclaration} - Container ToContainer(T value) => new Container(); - void M() - {{ - if (ToContainer(new {{ x = 0 }}) is null) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + {{typeDeclaration}} + Container ToContainer(T value) => new Container(); + void M() + { + if (ToContainer(new { x = 0 }) is [||]default) { } + } + } + """, + $$""" + class C + { + {{typeDeclaration}} + Container ToContainer(T value) => new Container(); + void M() + { + if (ToContainer(new { x = 0 }) is null) { } + } + } + """, s_csharp7_1above); } [Fact] @@ -746,20 +770,24 @@ void M() public async Task TestCSharp7_1_InIsPattern_SpecialTypeQualified(string @namespace, string type, string member) { await TestWithLanguageVersionsAsync( -$@"class C -{{ - void M() - {{ - if (default({@namespace}.{type}) is [||]default) {{ }} - }} -}}", -$@"class C -{{ - void M() - {{ - if (default({@namespace}.{type}) is {@namespace}.{type}.{member}) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M() + { + if (default({{@namespace}}.{{type}}) is [||]default) { } + } + } + """, + $$""" + class C + { + void M() + { + if (default({{@namespace}}.{{type}}) is {{@namespace}}.{{type}}.{{member}}) { } + } + } + """, s_csharp7_1above); } [Theory] @@ -769,22 +797,26 @@ void M() public async Task TestCSharp7_1_InIsPattern_SpecialTypeUnqualifiedWithUsing(string @namespace, string type, string member) { await TestWithLanguageVersionsAsync( -$@"using {@namespace}; -class C -{{ - void M() - {{ - if (default({type}) is [||]default) {{ }} - }} -}}", -$@"using {@namespace}; -class C -{{ - void M() - {{ - if (default({type}) is {type}.{member}) {{ }} - }} -}}", s_csharp7_1above); + $$""" + using {{@namespace}}; + class C + { + void M() + { + if (default({{type}}) is [||]default) { } + } + } + """, + $$""" + using {{@namespace}}; + class C + { + void M() + { + if (default({{type}}) is {{type}}.{{member}}) { } + } + } + """, s_csharp7_1above); } [Theory] @@ -794,13 +826,15 @@ void M() public async Task TestCSharp7_1_InIsPattern_NotForSpecialTypeUnqualifiedWithoutUsing(string type) { await TestMissingWithLanguageVersionsAsync( -$@"class C -{{ - void M() - {{ - if (default({type}) is [||]default) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M() + { + if (default({{type}}) is [||]default) { } + } + } + """, s_csharp7_1above); } [Fact] @@ -827,14 +861,16 @@ void M() public async Task TestCSharp7_1_InIsPattern_NotForInvalidType2(string expression) { await TestMissingWithLanguageVersionsAsync( -$@"class C -{{ - void M() - {{ - var value = {expression}; - if (value is [||]default) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M() + { + var value = {{expression}}; + if (value is [||]default) { } + } + } + """, s_csharp7_1above); } [Theory] @@ -846,13 +882,15 @@ void M() public async Task TestCSharp7_1_InIsPattern_NotForInvalidType3(string expression) { await TestMissingWithLanguageVersionsAsync( -$@"class C -{{ - void M() - {{ - if ({expression} is [||]default) {{ }} - }} -}}", s_csharp7_1above); + $$""" + class C + { + void M() + { + if ({{expression}} is [||]default) { } + } + } + """, s_csharp7_1above); } [Fact] diff --git a/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionFixAllTests.cs b/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionFixAllTests.cs index dec3e5328f397..efc2741cb4040 100644 --- a/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionFixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionFixAllTests.cs @@ -22,40 +22,42 @@ public async Task FixAllInDocument() { await new VerifyCS.Test { - TestCode = @" -using System; -using System.Linq; -using System.Collections.Generic; + TestCode = """ + using System; + using System.Linq; + using System.Collections.Generic; -class C -{ - static void M() - { - IEnumerable test = new List { ""hello"", ""world"", ""!"" }; - var test1 = [|test.Where(x => x.Equals('!')).Any()|]; - var test2 = [|test.Where(x => x.Equals('!')).SingleOrDefault()|]; - var test3 = [|test.Where(x => x.Equals('!')).Last()|]; - var test4 = [|test.Where(x => x.Equals('!')).Count()|]; - var test5 = [|test.Where(x => x.Equals('!')).FirstOrDefault()|]; - } -}", - FixedCode = @" -using System; -using System.Linq; -using System.Collections.Generic; + class C + { + static void M() + { + IEnumerable test = new List { "hello", "world", "!" }; + var test1 = [|test.Where(x => x.Equals('!')).Any()|]; + var test2 = [|test.Where(x => x.Equals('!')).SingleOrDefault()|]; + var test3 = [|test.Where(x => x.Equals('!')).Last()|]; + var test4 = [|test.Where(x => x.Equals('!')).Count()|]; + var test5 = [|test.Where(x => x.Equals('!')).FirstOrDefault()|]; + } + } + """, + FixedCode = """ + using System; + using System.Linq; + using System.Collections.Generic; -class C -{ - static void M() - { - IEnumerable test = new List { ""hello"", ""world"", ""!"" }; - var test1 = test.Any(x => x.Equals('!')); - var test2 = test.SingleOrDefault(x => x.Equals('!')); - var test3 = test.Last(x => x.Equals('!')); - var test4 = test.Count(x => x.Equals('!')); - var test5 = test.FirstOrDefault(x => x.Equals('!')); - } -}", + class C + { + static void M() + { + IEnumerable test = new List { "hello", "world", "!" }; + var test1 = test.Any(x => x.Equals('!')); + var test2 = test.SingleOrDefault(x => x.Equals('!')); + var test3 = test.Last(x => x.Equals('!')); + var test4 = test.Count(x => x.Equals('!')); + var test5 = test.FirstOrDefault(x => x.Equals('!')); + } + } + """, }.RunAsync(); } @@ -63,40 +65,42 @@ static void M() public async Task FixAllInDocumentExplicitCall() { - var testCode = @" -using System; -using System.Linq; -using System.Collections.Generic; + var testCode = """ + using System; + using System.Linq; + using System.Collections.Generic; -class C -{ - static void M() - { - IEnumerable test = new List { ""hello"", ""world"", ""!"" }; - var test1 = [|Enumerable.Where(test, x => x.Equals(""!"")).Any()|]; - var test2 = [|Enumerable.Where(test, x => x.Equals(""!"")).SingleOrDefault()|]; - var test3 = [|Enumerable.Where(test, x => x.Equals(""!"")).Last()|]; - var test4 = [|Enumerable.Where(test, x => x.Equals(""!"")).Count()|]; - var test5 = [|Enumerable.Where(test, x => x.Equals(""!"")).FirstOrDefault()|]; - } -}"; - var fixedCode = @" -using System; -using System.Linq; -using System.Collections.Generic; + class C + { + static void M() + { + IEnumerable test = new List { "hello", "world", "!" }; + var test1 = [|Enumerable.Where(test, x => x.Equals("!")).Any()|]; + var test2 = [|Enumerable.Where(test, x => x.Equals("!")).SingleOrDefault()|]; + var test3 = [|Enumerable.Where(test, x => x.Equals("!")).Last()|]; + var test4 = [|Enumerable.Where(test, x => x.Equals("!")).Count()|]; + var test5 = [|Enumerable.Where(test, x => x.Equals("!")).FirstOrDefault()|]; + } + } + """; + var fixedCode = """ + using System; + using System.Linq; + using System.Collections.Generic; -class C -{ - static void M() - { - IEnumerable test = new List { ""hello"", ""world"", ""!"" }; - var test1 = Enumerable.Any(test, x => x.Equals(""!"")); - var test2 = Enumerable.SingleOrDefault(test, x => x.Equals(""!"")); - var test3 = Enumerable.Last(test, x => x.Equals(""!"")); - var test4 = Enumerable.Count(test, x => x.Equals(""!"")); - var test5 = Enumerable.FirstOrDefault(test, x => x.Equals(""!"")); - } -}"; + class C + { + static void M() + { + IEnumerable test = new List { "hello", "world", "!" }; + var test1 = Enumerable.Any(test, x => x.Equals("!")); + var test2 = Enumerable.SingleOrDefault(test, x => x.Equals("!")); + var test3 = Enumerable.Last(test, x => x.Equals("!")); + var test4 = Enumerable.Count(test, x => x.Equals("!")); + var test5 = Enumerable.FirstOrDefault(test, x => x.Equals("!")); + } + } + """; await VerifyCS.VerifyCodeFixAsync(testCode, fixedCode); } @@ -106,42 +110,44 @@ public async Task NestedInDocument() await new VerifyCS.Test { - TestCode = @" -using System; -using System.Linq; -using System.Collections.Generic; + TestCode = """ + using System; + using System.Linq; + using System.Collections.Generic; -class C -{ - static void M() - { - var test = new List { ""hello"", ""world"", ""!"" }; - var test1 = [|test.Where(x => x.Equals('!')).Any()|]; - var test2 = [|test.Where(x => x.Equals('!')).SingleOrDefault()|]; - var test3 = [|test.Where(x => x.Equals('!')).Last()|]; - var test4 = test.Where(x => x.Equals('!')).Count(); - var test5 = from x in test where x.Equals('!') select x; - var test6 = [|test.Where(a => [|a.Where(s => s.Equals(""hello"")).FirstOrDefault()|].Equals(""hello"")).FirstOrDefault()|]; - } -}", - FixedCode = @" -using System; -using System.Linq; -using System.Collections.Generic; + class C + { + static void M() + { + var test = new List { "hello", "world", "!" }; + var test1 = [|test.Where(x => x.Equals('!')).Any()|]; + var test2 = [|test.Where(x => x.Equals('!')).SingleOrDefault()|]; + var test3 = [|test.Where(x => x.Equals('!')).Last()|]; + var test4 = test.Where(x => x.Equals('!')).Count(); + var test5 = from x in test where x.Equals('!') select x; + var test6 = [|test.Where(a => [|a.Where(s => s.Equals("hello")).FirstOrDefault()|].Equals("hello")).FirstOrDefault()|]; + } + } + """, + FixedCode = """ + using System; + using System.Linq; + using System.Collections.Generic; -class C -{ - static void M() - { - var test = new List { ""hello"", ""world"", ""!"" }; - var test1 = test.Any(x => x.Equals('!')); - var test2 = test.SingleOrDefault(x => x.Equals('!')); - var test3 = test.Last(x => x.Equals('!')); - var test4 = test.Where(x => x.Equals('!')).Count(); - var test5 = from x in test where x.Equals('!') select x; - var test6 = test.FirstOrDefault(a => a.FirstOrDefault(s => s.Equals(""hello"")).Equals(""hello"")); - } -}", + class C + { + static void M() + { + var test = new List { "hello", "world", "!" }; + var test1 = test.Any(x => x.Equals('!')); + var test2 = test.SingleOrDefault(x => x.Equals('!')); + var test3 = test.Last(x => x.Equals('!')); + var test4 = test.Where(x => x.Equals('!')).Count(); + var test5 = from x in test where x.Equals('!') select x; + var test6 = test.FirstOrDefault(a => a.FirstOrDefault(s => s.Equals("hello")).Equals("hello")); + } + } + """, }.RunAsync(); } } diff --git a/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionTests.cs b/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionTests.cs index 428427ee3baf5..c23af353e0b94 100644 --- a/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionTests.cs +++ b/src/Analyzers/CSharp/Tests/SimplifyLinqExpression/CSharpSimplifyLinqExpressionTests.cs @@ -38,42 +38,44 @@ public static async Task TestAllowedMethodTypes( { await new VerifyCS.Test { - TestCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - static void Main() - {{ - static IEnumerable Data() - {{ - yield return 1; - yield return 2; - }} - - var test = [|Data().Where({lambda}).{methodName}()|]; - }} -}}", - FixedCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - static void Main() - {{ - static IEnumerable Data() - {{ - yield return 1; - yield return 2; - }} - - var test = Data().{methodName}({lambda}); - }} -}}" + TestCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + static void Main() + { + static IEnumerable Data() + { + yield return 1; + yield return 2; + } + + var test = [|Data().Where({{lambda}}).{{methodName}}()|]; + } + } + """, + FixedCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + static void Main() + { + static IEnumerable Data() + { + yield return 1; + yield return 2; + } + + var test = Data().{{methodName}}({{lambda}}); + } + } + """ }.RunAsync(); } @@ -94,24 +96,25 @@ public static async Task TestWhereWithIndexMethodTypes( "LastOrDefault")] string methodName) { - var testCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - static void Main() - {{ - static IEnumerable Data() - {{ - yield return 1; - yield return 2; - }} - - var test = Data().Where({lambda}).{methodName}(); - }} -}}"; + var testCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + static void Main() + { + static IEnumerable Data() + { + yield return 1; + yield return 2; + } + + var test = Data().Where({{lambda}}).{{methodName}}(); + } + } + """; await VerifyCS.VerifyAnalyzerAsync(testCode); } @@ -134,26 +137,28 @@ public async Task TestQueryComprehensionSyntax( { await new VerifyCS.Test { - TestCode = $@" -using System.Linq; - -class Test -{{ - static void M() - {{ - var test1 = [|(from value in Enumerable.Range(0, 10) select value).Where({lambda}).{methodName}()|]; - }} -}}", - FixedCode = $@" -using System.Linq; - -class Test -{{ - static void M() - {{ - var test1 = (from value in Enumerable.Range(0, 10) select value).{methodName}({lambda}); - }} -}}" + TestCode = $$""" + using System.Linq; + + class Test + { + static void M() + { + var test1 = [|(from value in Enumerable.Range(0, 10) select value).Where({{lambda}}).{{methodName}}()|]; + } + } + """, + FixedCode = $$""" + using System.Linq; + + class Test + { + static void M() + { + var test1 = (from value in Enumerable.Range(0, 10) select value).{{methodName}}({{lambda}}); + } + } + """ }.RunAsync(); } @@ -170,50 +175,52 @@ public async Task TestMultiLineLambda(string methodName) { await new VerifyCS.Test { - TestCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - static void Main() - {{ - static IEnumerable Data() - {{ - yield return 1; - yield return 2; - }} - - var test = [|Data().Where(x => - {{ - Console.Write(x); - return x == 1; - }}).{methodName}()|]; - }} -}}", - FixedCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - static void Main() - {{ - static IEnumerable Data() - {{ - yield return 1; - yield return 2; - }} - - var test = Data().{methodName}(x => - {{ - Console.Write(x); - return x == 1; - }}); - }} -}}" + TestCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + static void Main() + { + static IEnumerable Data() + { + yield return 1; + yield return 2; + } + + var test = [|Data().Where(x => + { + Console.Write(x); + return x == 1; + }).{{methodName}}()|]; + } + } + """, + FixedCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + static void Main() + { + static IEnumerable Data() + { + yield return 1; + yield return 2; + } + + var test = Data().{{methodName}}(x => + { + Console.Write(x); + return x == 1; + }); + } + } + """ }.RunAsync(); } @@ -230,36 +237,38 @@ public async Task TestOutsideFunctionCallLambda(string methodName, string return { await new VerifyCS.Test { - TestCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - public static bool FooTest(string input) - {{ - return true; - }} - - static IEnumerable test = new List {{ ""hello"", ""world"", ""!"" }}; - {returnType} result = [|test.Where(x => FooTest(x)).{methodName}()|]; -}}", - FixedCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - public static bool FooTest(string input) - {{ - return true; - }} - - static IEnumerable test = new List {{ ""hello"", ""world"", ""!"" }}; - {returnType} result = test.{methodName}(x => FooTest(x)); -}}" + TestCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + public static bool FooTest(string input) + { + return true; + } + + static IEnumerable test = new List { "hello", "world", "!" }; + {{returnType}} result = [|test.Where(x => FooTest(x)).{{methodName}}()|]; + } + """, + FixedCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + public static bool FooTest(string input) + { + return true; + } + + static IEnumerable test = new List { "hello", "world", "!" }; + {{returnType}} result = test.{{methodName}}(x => FooTest(x)); + } + """ }.RunAsync(); } @@ -274,22 +283,23 @@ public static bool FooTest(string input) [InlineData("LastOrDefault")] public async Task TestQueryableIsNotConsidered(string methodName) { - var source = $@" -using System; -using System.Linq; -using System.Collections.Generic; -namespace demo -{{ - class Test - {{ - void M() - {{ - List testvar1 = new List {{ 1, 2, 3, 4, 5, 6, 7, 8 }}; - IQueryable testvar2 = testvar1.AsQueryable().Where(x => x % 2 == 0); - var output = testvar2.Where(x => x == 4).{methodName}(); - }} - }} -}}"; + var source = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + namespace demo + { + class Test + { + void M() + { + List testvar1 = new List { 1, 2, 3, 4, 5, 6, 7, 8 }; + IQueryable testvar2 = testvar1.AsQueryable().Where(x => x % 2 == 0); + var output = testvar2.Where(x => x == 4).{{methodName}}(); + } + } + } + """; await VerifyCS.VerifyAnalyzerAsync(source); } @@ -316,32 +326,34 @@ public async Task TestNestedLambda( "LastOrDefault")] string secondMethod) { - var testCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - void M() - {{ - IEnumerable test = new List {{ ""hello"", ""world"", ""!"" }}; - var test5 = [|test.Where(a => [|a.Where(s => s.Equals(""hello"")).{secondMethod}()|].Equals(""hello"")).{firstMethod}()|]; - }} -}}"; - var fixedCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - void M() - {{ - IEnumerable test = new List {{ ""hello"", ""world"", ""!"" }}; - var test5 = test.{firstMethod}(a => a.{secondMethod}(s => s.Equals(""hello"")).Equals(""hello"")); - }} -}}"; + var testCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + void M() + { + IEnumerable test = new List { "hello", "world", "!" }; + var test5 = [|test.Where(a => [|a.Where(s => s.Equals("hello")).{{secondMethod}}()|].Equals("hello")).{{firstMethod}}()|]; + } + } + """; + var fixedCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + void M() + { + IEnumerable test = new List { "hello", "world", "!" }; + var test5 = test.{{firstMethod}}(a => a.{{secondMethod}}(s => s.Equals("hello")).Equals("hello")); + } + } + """; await VerifyCS.VerifyCodeFixAsync( testCode, fixedCode); @@ -360,34 +372,36 @@ public async Task TestExplicitEnumerableCall(string methodName) { await new VerifyCS.Test { - TestCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; -using System.Linq.Expressions; - -class Test -{{ - static void Main() - {{ - IEnumerable test = new List {{ 1, 2, 3, 4, 5}}; - [|Enumerable.Where(test, (x => x == 1)).{methodName}()|]; - }} -}}", - FixedCode = $@" -using System; -using System.Linq; -using System.Collections.Generic; -using System.Linq.Expressions; - -class Test -{{ - static void Main() - {{ - IEnumerable test = new List {{ 1, 2, 3, 4, 5}}; - Enumerable.{methodName}(test, (x => x == 1)); - }} -}}" + TestCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + using System.Linq.Expressions; + + class Test + { + static void Main() + { + IEnumerable test = new List { 1, 2, 3, 4, 5}; + [|Enumerable.Where(test, (x => x == 1)).{{methodName}}()|]; + } + } + """, + FixedCode = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + using System.Linq.Expressions; + + class Test + { + static void Main() + { + IEnumerable test = new List { 1, 2, 3, 4, 5}; + Enumerable.{{methodName}}(test, (x => x == 1)); + } + } + """ }.RunAsync(); } @@ -439,19 +453,20 @@ static void Main() [InlineData("LastOrDefault")] public async Task TestArgumentsInSecondCall(string methodName) { - var source = $@" -using System; -using System.Linq; -using System.Collections.Generic; - -class Test -{{ - static void M() - {{ - IEnumerable test1 = new List{{ ""hello"", ""world"", ""!"" }}; - var test2 = test1.Where(x => x == ""!"").{methodName}(x => x.Length == 1); - }} -}}"; + var source = $$""" + using System; + using System.Linq; + using System.Collections.Generic; + + class Test + { + static void M() + { + IEnumerable test1 = new List{ "hello", "world", "!" }; + var test2 = test1.Where(x => x == "!").{{methodName}}(x => x.Length == 1); + } + } + """; await VerifyCS.VerifyAnalyzerAsync(source); } diff --git a/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs b/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs index a13dac7640d1c..de5b58c0986ab 100644 --- a/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs +++ b/src/Analyzers/CSharp/Tests/UpdateLegacySuppressions/UpdateLegacySuppressionsTests.cs @@ -39,47 +39,49 @@ public void TestStandardProperty(AnalyzerProperty property) [Theory] public async Task LegacySuppressions(string scope, string target, string fixedTarget) { - var input = $@" -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Scope = ""{scope}"", Target = {{|#0:""{target}""|}})] + var input = $$""" + [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Category", "Id: Title", Scope = "{{scope}}", Target = {|#0:"{{target}}"|})] -namespace N -{{ - class C - {{ - private int F; - public int P {{ get; set; }} - public void M() {{ }} - public int M2(T t) => 0; - public event System.EventHandler E; + namespace N + { + class C + { + private int F; + public int P { get; set; } + public void M() { } + public int M2(T t) => 0; + public event System.EventHandler E; - class D - {{ - }} - }} -}}"; + class D + { + } + } + } + """; var expectedDiagnostic = VerifyCS.Diagnostic(AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.LegacyFormatTargetDescriptor) .WithLocation(0) .WithArguments(target); - var fixedCode = $@" -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Scope = ""{scope}"", Target = ""{fixedTarget}"")] + var fixedCode = $$""" + [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Category", "Id: Title", Scope = "{{scope}}", Target = "{{fixedTarget}}")] -namespace N -{{ - class C - {{ - private int F; - public int P {{ get; set; }} - public void M() {{ }} - public int M2(T t) => 0; - public event System.EventHandler E; + namespace N + { + class C + { + private int F; + public int P { get; set; } + public void M() { } + public int M2(T t) => 0; + public event System.EventHandler E; - class D - {{ - }} - }} -}}"; + class D + { + } + } + } + """; await VerifyCS.VerifyCodeFixAsync(input, expectedDiagnostic, fixedCode); } } diff --git a/src/Analyzers/CSharp/Tests/UpgradeProject/UpgradeProjectTests.cs b/src/Analyzers/CSharp/Tests/UpgradeProject/UpgradeProjectTests.cs index 9fc18b9ce3389..33aa38939b9f2 100644 --- a/src/Analyzers/CSharp/Tests/UpgradeProject/UpgradeProjectTests.cs +++ b/src/Analyzers/CSharp/Tests/UpgradeProject/UpgradeProjectTests.cs @@ -147,11 +147,12 @@ void A() public async Task UpgradeProjectFromCSharp7ToLatest() { await TestLanguageVersionUpgradedAsync( -$@" -class Program -{{ -#error version:[|{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}|] -}}", + $$""" + class Program + { + #error version:[|{{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}}|] + } + """, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion(), new CSharpParseOptions(LanguageVersion.CSharp7)); } @@ -194,11 +195,12 @@ public ValueTuple(T1 item1, T2 item2) public async Task UpgradeProjectFromCSharp7_1ToLatest() { await TestLanguageVersionUpgradedAsync( -$@" -class Program -{{ -#error version:[|{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}|] -}}", + $$""" + class Program + { + #error version:[|{{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}}|] + } + """, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion(), new CSharpParseOptions(LanguageVersion.CSharp7_1)); } @@ -258,11 +260,12 @@ public static void M(T x) where T: Base public async Task UpgradeProjectFromCSharp7_2ToLatest() { await TestLanguageVersionUpgradedAsync( -$@" -class Program -{{ -#error version:[|{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}|] -}}", + $$""" + class Program + { + #error version:[|{{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}}|] + } + """, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion(), new CSharpParseOptions(LanguageVersion.CSharp7_2)); } @@ -328,11 +331,12 @@ public class X where T : [|System.MulticastDelegate|] public async Task UpgradeProjectFromCSharp7_3ToLatest() { await TestLanguageVersionUpgradedAsync( -$@" -class Program -{{ -#error version:[|{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}|] -}}", + $$""" + class Program + { + #error version:[|{{LanguageVersion.Latest.MapSpecifiedToEffectiveVersion().ToDisplayString()}}|] + } + """, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion(), new CSharpParseOptions(LanguageVersion.CSharp7_3)); } @@ -341,11 +345,12 @@ class Program public async Task UpgradeProjectFromCSharp7_3To8_0() { await TestLanguageVersionUpgradedAsync( -$@" -class Program -{{ -#error version:[|{LanguageVersion.CSharp8.ToDisplayString()}|] -}}", + $$""" + class Program + { + #error version:[|{{LanguageVersion.CSharp8.ToDisplayString()}}|] + } + """, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion(), new CSharpParseOptions(LanguageVersion.CSharp7_3)); } @@ -506,10 +511,10 @@ void A() """, - new[] { + [ string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, "7.0"), string.Format(CSharpCodeFixesResources.Upgrade_all_csharp_projects_to_language_version_0, "7.0") - }); + ]); } [Fact] @@ -536,11 +541,10 @@ void A() """, - new[] - { + [ string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, "8.0"), string.Format(CSharpCodeFixesResources.Upgrade_all_csharp_projects_to_language_version_0, "8.0") - } + ] ); } @@ -566,9 +570,9 @@ void A() """, - new[] { + [ string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, "7.0") - }); + ]); } [Fact] @@ -595,9 +599,9 @@ void A() """, - new[] { + [ string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, "7.0") - }); + ]); } [Fact] @@ -606,34 +610,35 @@ public async Task OnlyOfferFixAllProjectsFromCSharp6ToDefaultWhenApplicable() var defaultVersion = LanguageVersion.Default.MapSpecifiedToEffectiveVersion().ToDisplayString(); await TestExactActionSetOfferedAsync( -$@" - - -class C -{{ - void A() - {{ -#error version:[|{defaultVersion}|] - }} -}} - - - - - - -", - new[] { + $$""" + + + + class C + { + void A() + { + #error version:[|{{defaultVersion}}|] + } + } + + + + + + + + """, + [ string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, defaultVersion), string.Format(CSharpCodeFixesResources.Upgrade_all_csharp_projects_to_language_version_0, defaultVersion) - }); + ]); } [Fact] public async Task OnlyOfferFixAllProjectsToCSharp8WhenApplicable() { await TestExactActionSetOfferedAsync( - """ @@ -650,9 +655,7 @@ class C """, - new[] { - string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, "8.0"), - }); + [string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, "8.0")]); } [Fact] @@ -660,28 +663,29 @@ public async Task OnlyOfferFixAllProjectsToDefaultWhenApplicable() { var defaultEffectiveVersion = LanguageVersion.Default.MapSpecifiedToEffectiveVersion().ToDisplayString(); await TestExactActionSetOfferedAsync( - -$@" - - -class C -{{ - void A() - {{ -#error version:[|{defaultEffectiveVersion}|] - }} -}} - - - - - - -", - new[] { + $$""" + + + + class C + { + void A() + { + #error version:[|{{defaultEffectiveVersion}}|] + } + } + + + + + + + + """, + [ string.Format(CSharpCodeFixesResources.Upgrade_this_project_to_csharp_language_version_0, defaultEffectiveVersion), string.Format(CSharpCodeFixesResources.Upgrade_all_csharp_projects_to_language_version_0, defaultEffectiveVersion) - }); + ]); } [Fact] @@ -1091,8 +1095,9 @@ public record Base public async Task UpgradeProjectForPrimaryConstructors_Class() { await TestLanguageVersionUpgradedAsync( -@" -class Program[|()|];", + """ + class Program[|()|]; + """, LanguageVersion.CSharp12, new CSharpParseOptions(LanguageVersion.CSharp11)); } @@ -1101,8 +1106,9 @@ class Program[|()|];", public async Task UpgradeProjectForPrimaryConstructors_Struct() { await TestLanguageVersionUpgradedAsync( -@" -struct Program[|()|];", + """ + struct Program[|()|]; + """, LanguageVersion.CSharp12, new CSharpParseOptions(LanguageVersion.CSharp11)); } @@ -1111,8 +1117,9 @@ struct Program[|()|];", public async Task UpgradeProjectForSemicolonBody_Class() { await TestLanguageVersionUpgradedAsync( -@" -class Program[|;|]", + """ + class Program[|;|] + """, LanguageVersion.CSharp12, new CSharpParseOptions(LanguageVersion.CSharp11)); } @@ -1121,8 +1128,9 @@ class Program[|;|]", public async Task UpgradeProjectForSemicolonBody_Struct() { await TestLanguageVersionUpgradedAsync( -@" -struct Program[|;|]", + """ + struct Program[|;|] + """, LanguageVersion.CSharp12, new CSharpParseOptions(LanguageVersion.CSharp11)); } @@ -1131,8 +1139,9 @@ struct Program[|;|]", public async Task UpgradeProjectForSemicolonBody_Interface() { await TestLanguageVersionUpgradedAsync( -@" -interface Program[|;|]", + """ + interface Program[|;|] + """, LanguageVersion.CSharp12, new CSharpParseOptions(LanguageVersion.CSharp11)); } @@ -1141,8 +1150,9 @@ interface Program[|;|]", public async Task UpgradeProjectForSemicolonBody_Enum() { await TestLanguageVersionUpgradedAsync( -@" -enum Program[|;|]", + """ + enum Program[|;|] + """, LanguageVersion.CSharp12, new CSharpParseOptions(LanguageVersion.CSharp11)); } diff --git a/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForArrayTests.cs b/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForArrayTests.cs index b4660575d2304..c28b34a335e15 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForArrayTests.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForArrayTests.cs @@ -193,7 +193,7 @@ class C } [Fact] - public async Task TestNotWithIncompatibleExplicitArrays() + public async Task TestNotWithIncompatibleExplicitArrays_Strict() { await new VerifyCS.Test { @@ -204,6 +204,31 @@ class C } """, LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ + }.RunAsync(); + } + + [Fact] + public async Task TestNotWithIncompatibleExplicitArrays() + { + await new VerifyCS.Test + { + TestCode = """ + class C + { + object[] i = [|[|new|] string[]|] { "" }; + } + """, + FixedCode = """ + class C + { + object[] i = [""]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, }.RunAsync(); } @@ -365,6 +390,27 @@ class C [Fact] public async Task TestNotWithIncompatibleImplicitArrays() + { + await new VerifyCS.Test + { + TestCode = """ + class C + { + object[] i = [|[|new|][]|] { "" }; + } + """, + FixedCode = """ + class C + { + object[] i = [""]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestNotWithIncompatibleImplicitArrays_Strict() { await new VerifyCS.Test { @@ -375,6 +421,10 @@ class C } """, LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ }.RunAsync(); } @@ -464,7 +514,7 @@ class C [Theory, CombinatorialData] public async Task TestNotWithVar_ExplicitArrayType( - [CombinatorialValues(new object[] { "var", "object", "dynamic" })] string type) + [CombinatorialValues(["var", "object", "dynamic"])] string type) { await new VerifyCS.Test { @@ -483,7 +533,7 @@ void M() [Theory, CombinatorialData] public async Task TestNotWithVar_ExplicitArrayType2( - [CombinatorialValues(new object[] { "var", "object", "dynamic" })] string type) + [CombinatorialValues(["var", "object", "dynamic"])] string type) { await new VerifyCS.Test { @@ -502,7 +552,7 @@ void M() [Theory, CombinatorialData] public async Task TestNotWithVar_ImplicitArrayType( - [CombinatorialValues(new object[] { "var", "object", "dynamic" })] string type) + [CombinatorialValues(["var", "object", "dynamic"])] string type) { await new VerifyCS.Test { @@ -521,7 +571,7 @@ void M() [Theory, CombinatorialData] public async Task TestNotWithVar_ImplicitArrayType2( - [CombinatorialValues(new object[] { "var", "object", "dynamic" })] string type) + [CombinatorialValues(["var", "object", "dynamic"])] string type) { await new VerifyCS.Test { @@ -4606,4 +4656,512 @@ static void M(string[] args) { } TestState = { OutputKind = OutputKind.ConsoleApplication } }.RunAsync(); } + + [Fact] + public async Task TestNullableArrays1() + { + await new VerifyCS.Test + { + TestCode = """ + #nullable disable + + using System; + + class C + { + void M() + { + GetActiveStatementDebugInfosCSharp( + [|[|new|][]|] { GetGeneratedCodeFromMarkedSource() }, + filePaths: [|[|new|][]|] { this.filePath }); + } + + #nullable enable + + public static void GetActiveStatementDebugInfosCSharp( + string[] markedSources, + string[]? filePaths = null, + int[]? methodRowIds = null, + Guid[]? modules = null, + int[]? methodVersions = null, + int[]? ilOffsets = null) + { + } + + private static string GetGeneratedCodeFromMarkedSource() => ""; + + private string? filePath; + } + """, + FixedCode = """ + #nullable disable + + using System; + + class C + { + void M() + { + GetActiveStatementDebugInfosCSharp( + [GetGeneratedCodeFromMarkedSource()], + filePaths: [this.filePath]); + } + + #nullable enable + + public static void GetActiveStatementDebugInfosCSharp( + string[] markedSources, + string[]? filePaths = null, + int[]? methodRowIds = null, + Guid[]? modules = null, + int[]? methodVersions = null, + int[]? ilOffsets = null) + { + } + + private static string GetGeneratedCodeFromMarkedSource() => ""; + + private string? filePath; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray1() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = [|[|new|] object[][]|] + { + [|[|new|][]|] { "[]", "[]" }, + [|[|new|][]|] { "[]", "[]" }, + }; + } + """, + FixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = + [ + ["[]", "[]"], + ["[]", "[]"], + ]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray1_Strict() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = new object[][] + { + new[] { "[]", "[]" }, + new[] { "[]", "[]" }, + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray2() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = + [ + [|[|new|][]|] { "[]", "[]" }, + [|[|new|][]|] { "[]", "[]" }, + ]; + } + """, + FixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = + [ + ["[]", "[]"], + ["[]", "[]"], + ]; + } + """, + BatchFixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = + [ + ["[]", "[]"], + ["[]", "[]"], + ]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray2_Strict() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = + [ + new[] { "[]", "[]" }, + new[] { "[]", "[]" }, + ]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray3() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable> EmptyOrConstantsOnly = [|[|new|] object[][]|] + { + [|[|new|][]|] { "[]", "[]" }, + [|[|new|][]|] { "[]", "[]" }, + }; + } + """, + FixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable> EmptyOrConstantsOnly = + [ + ["[]", "[]"], + ["[]", "[]"], + ]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray3_Strict() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable> EmptyOrConstantsOnly = new object[][] + { + new[] { "[]", "[]" }, + new[] { "[]", "[]" }, + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray4() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable> EmptyOrConstantsOnly = [|[|new|] object[][]|] + { + ["[]", "[]"], + ["[]", "[]"], + }; + } + """, + FixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable> EmptyOrConstantsOnly = + [ + ["[]", "[]"], + ["[]", "[]"], + ]; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray4_Strict() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable> EmptyOrConstantsOnly = new object[][] + { + ["[]", "[]"], + ["[]", "[]"], + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray5() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = [|[|new|] object[][]|] + { + [|[|new|][]|] { "[]", "[]" }, + [|[|new|][]|] { "[]", "[]" }, + }; + } + """, + FixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = + [ + new[] { "[]", "[]" }, + new[] { "[]", "[]" }, + ]; + } + """, + BatchFixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly IEnumerable EmptyOrConstantsOnly = new object[][] + { + ["[]", "[]"], + ["[]", "[]"], + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestMultiDimensionalArray6() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly object[] EmptyOrConstantsOnly = [|[|new|] object[][]|] + { + [|[|new|][]|] { "[]", "[]" }, + [|[|new|][]|] { "[]", "[]" }, + }; + } + """, + FixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly object[] EmptyOrConstantsOnly = + [ + new[] { "[]", "[]" }, + new[] { "[]", "[]" }, + ]; + } + """, + BatchFixedCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly object[] EmptyOrConstantsOnly = new object[][] + { + ["[]", "[]"], + ["[]", "[]"], + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestArray1() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly object EmptyOrConstantsOnly = new object[] + { + "" + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task TestArray2() + { + await new VerifyCS.Test + { + TestCode = + """ + using System; + using System.Collections.Generic; + using System.Linq.Expressions; + + class C + { + public static readonly object EmptyOrConstantsOnly = new[] + { + "" + }; + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } } diff --git a/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForEmptyTests.cs b/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForEmptyTests.cs index 017f5dab5eae9..a8319d76ccc68 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForEmptyTests.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionExpression/UseCollectionExpressionForEmptyTests.cs @@ -116,6 +116,35 @@ void M() [Fact] public async Task ArrayEmpty3() + { + await new VerifyCS.Test + { + TestCode = """ + using System; + class C + { + void M() + { + object[] v = Array.[|Empty|](); + } + } + """, + FixedCode = """ + using System; + class C + { + void M() + { + object[] v = []; + } + } + """, + LanguageVersion = LanguageVersion.CSharp12, + }.RunAsync(); + } + + [Fact] + public async Task ArrayEmpty3_Strict() { await new VerifyCS.Test { @@ -130,6 +159,10 @@ void M() } """, LanguageVersion = LanguageVersion.CSharp12, + EditorConfig = """ + [*] + dotnet_style_prefer_collection_expression=when_types_exactly_match + """ }.RunAsync(); } diff --git a/src/Analyzers/CSharp/Tests/UseConditionalExpression/UseConditionalExpressionForReturnTests.cs b/src/Analyzers/CSharp/Tests/UseConditionalExpression/UseConditionalExpressionForReturnTests.cs index 2edc0271aa299..1165bc343c5d5 100644 --- a/src/Analyzers/CSharp/Tests/UseConditionalExpression/UseConditionalExpressionForReturnTests.cs +++ b/src/Analyzers/CSharp/Tests/UseConditionalExpression/UseConditionalExpressionForReturnTests.cs @@ -478,6 +478,78 @@ int M() """); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70750")] + public async Task TestMissingWithChecked() + { + await TestMissingInRegularAndScriptAsync( + """ + class C + { + int M() + { + int x = 0; + int y = 0; + [||]if (x < 0) + { + throw new System.Exception(); + } + checked + { + return x - y; + } + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70750")] + public async Task TestMissingWithUnchecked() + { + await TestMissingInRegularAndScriptAsync( + """ + class C + { + int M() + { + int x = 0; + int y = 0; + [||]if (x < 0) + { + throw new System.Exception(); + } + unchecked + { + return x - y; + } + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70750")] + public async Task TestMissingWithUnsafe() + { + await TestMissingInRegularAndScriptAsync( + """ + class C + { + int M() + { + int x = 0; + int y = 0; + [||]if (x < 0) + { + throw new System.Exception(); + } + unsafe + { + return x - y; + } + } + } + """); + } + [Fact] public async Task TestConversion1_CSharp8() { diff --git a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests.cs b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests.cs index 18abdad730bd0..42e382a57ad32 100644 --- a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests.cs +++ b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests.cs @@ -301,8 +301,7 @@ void Method() """, new TestParameters(options: ExplicitTypeEverywhere())); } - [WorkItem("https://github.com/dotnet/roslyn/issues/29718")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/29718")] public async Task NotOnErrorConvertedType_ForEachVariableStatement() { await TestMissingInRegularAndScriptAsync( @@ -324,8 +323,7 @@ void M() """, new TestParameters(options: ExplicitTypeEverywhere())); } - [WorkItem("https://github.com/dotnet/roslyn/issues/29718")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/29718")] public async Task NotOnErrorConvertedType_AssignmentExpressionStatement() { await TestMissingInRegularAndScriptAsync( diff --git a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests_FixAllTests.cs index e3ce481ff60c1..1e574440d84a0 100644 --- a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseExplicitTypeTests_FixAllTests.cs @@ -19,111 +19,113 @@ public partial class UseExplicitTypeTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocumentScope_PreferExplicitTypeEverywhere() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInDocument:var|} i1 = 0; - var p = new Program(); - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - int i1 = 0; - Program p = new Program(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInDocument:var|} i1 = 0; + var p = new Program(); + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + int i1 = 0; + Program p = new Program(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ExplicitTypeEverywhere()); } @@ -133,111 +135,113 @@ static int F(int x, int y) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProject_PreferExplicitTypeEverywhere() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInProject:var|} i1 = 0; - var p = new Program(); - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - var i2 = 0; - var p2 = new Program2(); - var tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i3 = 0; - Program2 p3 = new Program2(); - Tuple<bool, int> tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - int i1 = 0; - Program p = new Program(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i2 = 0; - Program2 p2 = new Program2(); - Tuple<bool, int> tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i3 = 0; - Program2 p3 = new Program2(); - Tuple<bool, int> tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInProject:var|} i1 = 0; + var p = new Program(); + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + var i2 = 0; + var p2 = new Program2(); + var tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i3 = 0; + Program2 p3 = new Program2(); + Tuple<bool, int> tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + int i1 = 0; + Program p = new Program(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i2 = 0; + Program2 p2 = new Program2(); + Tuple<bool, int> tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i3 = 0; + Program2 p3 = new Program2(); + Tuple<bool, int> tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ExplicitTypeEverywhere()); } @@ -247,111 +251,113 @@ static int F(int x, int y) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution_PreferExplicitTypeEverywhere() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInSolution:var|} i1 = 0; - var p = new Program(); - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - var i2 = 0; - var p2 = new Program2(); - var tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - var i3 = 0; - var p3 = new Program2(); - var tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - int i1 = 0; - Program p = new Program(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i2 = 0; - Program2 p2 = new Program2(); - Tuple<bool, int> tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i3 = 0; - Program2 p3 = new Program2(); - Tuple<bool, int> tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInSolution:var|} i1 = 0; + var p = new Program(); + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + var i2 = 0; + var p2 = new Program2(); + var tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + var i3 = 0; + var p3 = new Program2(); + var tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + int i1 = 0; + Program p = new Program(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i2 = 0; + Program2 p2 = new Program2(); + Tuple<bool, int> tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i3 = 0; + Program2 p3 = new Program2(); + Tuple<bool, int> tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ExplicitTypeEverywhere()); } @@ -361,47 +367,49 @@ static int F(int x, int y) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocumentScope_PreferExplicitTypeExceptWhereApparent() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInDocument:var|} p = this; - var i1 = 0; - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - Program p = this; - int i1 = 0; - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInDocument:var|} p = this; + var i1 = 0; + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + Program p = this; + int i1 = 0; + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ExplicitTypeExceptWhereApparent()); } diff --git a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs index fb61f61e1b054..a2e9068b26ff4 100644 --- a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs +++ b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests.cs @@ -2838,8 +2838,7 @@ static void Main(string[] args) """, new TestParameters(options: ImplicitTypeEverywhere())); } - [WorkItem("https://github.com/dotnet/roslyn/issues/39171")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39171")] public async Task NoSuggestionForSwitchExpressionDifferentTypes() { await TestMissingInRegularAndScriptAsync( @@ -2865,8 +2864,7 @@ public static void Test(string name) """, new TestParameters(options: ImplicitTypeEverywhere())); } - [WorkItem("https://github.com/dotnet/roslyn/issues/39171")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/39171")] public async Task SuggestSwitchExpressionSameOrInheritedTypes() { await TestInRegularAndScriptAsync( diff --git a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests_FixAllTests.cs index d6fd660458ed3..3609f9a2c5488 100644 --- a/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/UseImplicitOrExplicitType/UseImplicitTypeTests_FixAllTests.cs @@ -19,111 +19,113 @@ public partial class UseImplicitTypeTests [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocumentScope_PreferImplicitTypeEverywhere() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInDocument:int|} i1 = 0; - Program p = new Program(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - var i1 = 0; - var p = new Program(); - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i1 = 0; - Program2 p = new Program2(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInDocument:int|} i1 = 0; + Program p = new Program(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + var i1 = 0; + var p = new Program(); + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i1 = 0; + Program2 p = new Program2(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ImplicitTypeEverywhere()); } @@ -133,111 +135,113 @@ static int F(int x, int y) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInProject_PreferImplicitTypeEverywhere() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInProject:int|} i1 = 0; - Program p = new Program(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i2 = 0; - Program2 p2 = new Program2(); - Tuple<bool, int> tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i3 = 0; - Program2 p3 = new Program2(); - Tuple<bool, int> tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - var i1 = 0; - var p = new Program(); - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - var i2 = 0; - var p2 = new Program2(); - var tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i3 = 0; - Program2 p3 = new Program2(); - Tuple<bool, int> tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInProject:int|} i1 = 0; + Program p = new Program(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i2 = 0; + Program2 p2 = new Program2(); + Tuple<bool, int> tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i3 = 0; + Program2 p3 = new Program2(); + Tuple<bool, int> tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + var i1 = 0; + var p = new Program(); + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + var i2 = 0; + var p2 = new Program2(); + var tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i3 = 0; + Program2 p3 = new Program2(); + Tuple<bool, int> tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ImplicitTypeEverywhere()); } @@ -247,111 +251,113 @@ static int F(int x, int y) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInSolution_PreferImplicitTypeEverywhere() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInSolution:int|} i1 = 0; - Program p = new Program(); - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i2 = 0; - Program2 p2 = new Program2(); - Tuple<bool, int> tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - int i3 = 0; - Program2 p3 = new Program2(); - Tuple<bool, int> tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - var i1 = 0; - var p = new Program(); - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - var i2 = 0; - var p2 = new Program2(); - var tuple2 = Tuple.Create(true, 1); - - return i2; - } -} - - - - -using System; - -class Program2 -{ - static int F(int x, int y) - { - var i3 = 0; - var p3 = new Program2(); - var tuple3 = Tuple.Create(true, 1); - - return i3; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInSolution:int|} i1 = 0; + Program p = new Program(); + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i2 = 0; + Program2 p2 = new Program2(); + Tuple<bool, int> tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + int i3 = 0; + Program2 p3 = new Program2(); + Tuple<bool, int> tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + var i1 = 0; + var p = new Program(); + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + using System; + + class Program2 + { + static int F(int x, int y) + { + var i2 = 0; + var p2 = new Program2(); + var tuple2 = Tuple.Create(true, 1); + + return i2; + } + } + + + + + using System; + + class Program2 + { + static int F(int x, int y) + { + var i3 = 0; + var p3 = new Program2(); + var tuple3 = Tuple.Create(true, 1); + + return i3; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ImplicitTypeEverywhere()); } @@ -361,47 +367,49 @@ static int F(int x, int y) [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] public async Task TestFixAllInDocumentScope_PreferBuiltInTypes() { - var input = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - {|FixAllInDocument:Program|} p = new Program(); - int i1 = 0; - Tuple<bool, int> tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; - - var expected = @" - - - -using System; - -class Program -{ - static int F(int x, int y) - { - var p = new Program(); - int i1 = 0; - var tuple = Tuple.Create(true, 1); - - return i1; - } -} - - -"; + var input = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + {|FixAllInDocument:Program|} p = new Program(); + int i1 = 0; + Tuple<bool, int> tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; + + var expected = """ + + + + using System; + + class Program + { + static int F(int x, int y) + { + var p = new Program(); + int i1 = 0; + var tuple = Tuple.Create(true, 1); + + return i1; + } + } + + + + """; await TestInRegularAndScriptAsync(input, expected, options: ImplicitTypeButKeepIntrinsics()); } diff --git a/src/Analyzers/CSharp/Tests/UseIndexOrRangeOperator/UseRangeOperatorTests.cs b/src/Analyzers/CSharp/Tests/UseIndexOrRangeOperator/UseRangeOperatorTests.cs index 069a272df6c5d..501c2444e9b39 100644 --- a/src/Analyzers/CSharp/Tests/UseIndexOrRangeOperator/UseRangeOperatorTests.cs +++ b/src/Analyzers/CSharp/Tests/UseIndexOrRangeOperator/UseRangeOperatorTests.cs @@ -999,27 +999,29 @@ public class Test public async Task TestExpressionWithNullConditionalAccessVariations(string subStringCode, string rangeCode) { var source = -@$" -public class C -{{ - public string Prop {{ get; set; }} -}} -public class Test -{{ - public object M(C c) - => {subStringCode}; -}}"; + $$""" + public class C + { + public string Prop { get; set; } + } + public class Test + { + public object M(C c) + => {{subStringCode}}; + } + """; var fixedSource = -@$" -public class C -{{ - public string Prop {{ get; set; }} -}} -public class Test -{{ - public object M(C c) - => {rangeCode}; -}}"; + $$""" + public class C + { + public string Prop { get; set; } + } + public class Test + { + public object M(C c) + => {{rangeCode}}; + } + """; await new VerifyCS.Test { ReferenceAssemblies = ReferenceAssemblies.NetCore.NetCoreApp31, diff --git a/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForCastAndEqualityOperatorTests.cs b/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForCastAndEqualityOperatorTests.cs index 225e1e7e17f59..2f826bff7d9d2 100644 --- a/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForCastAndEqualityOperatorTests.cs +++ b/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForCastAndEqualityOperatorTests.cs @@ -72,7 +72,7 @@ void M(string s) } } """, -new[] { CSharpAnalyzersResources.Use_is_null_check }); +[CSharpAnalyzersResources.Use_is_null_check]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58483")] @@ -91,7 +91,7 @@ void M(string s) } } """, -new[] { CSharpAnalyzersResources.Use_is_object_check }, +[CSharpAnalyzersResources.Use_is_object_check], new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8))); } @@ -111,7 +111,7 @@ void M(string s) } } """, -new[] { CSharpAnalyzersResources.Use_is_not_null_check }, +[CSharpAnalyzersResources.Use_is_not_null_check], new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9))); } diff --git a/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForReferenceEqualsTests.cs b/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForReferenceEqualsTests.cs index 8516210e63f3e..cfb271ccd5c09 100644 --- a/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForReferenceEqualsTests.cs +++ b/src/Analyzers/CSharp/Tests/UseIsNullCheck/UseIsNullCheckForReferenceEqualsTests.cs @@ -76,7 +76,7 @@ void M(string s) } } """, -new[] { CSharpAnalyzersResources.Use_is_null_check }); +[CSharpAnalyzersResources.Use_is_null_check]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58483")] @@ -95,7 +95,7 @@ void M(string s) } } """, -new[] { CSharpAnalyzersResources.Use_is_object_check }, +[CSharpAnalyzersResources.Use_is_object_check], new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8))); } @@ -115,7 +115,7 @@ void M(string s) } } """, -new[] { CSharpAnalyzersResources.Use_is_not_null_check }, +[CSharpAnalyzersResources.Use_is_not_null_check], new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9))); } diff --git a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests.cs b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests.cs index a9295d4006df8..0b0f4e0e26c42 100644 --- a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests.cs +++ b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests.cs @@ -63,21 +63,25 @@ public async Task InlineTypeCheck2(string input, string output) private async Task TestStatement(string input, string output, LanguageVersion version = LanguageVersion.CSharp8) { await TestInRegularAndScript1Async( -$@"class C -{{ - void M(object o) - {{ - [|var|] x = o as string; - {input} - }} -}}", -$@"class C -{{ - void M(object o) - {{ - {output} - }} -}}", new TestParameters(CSharpParseOptions.Default.WithLanguageVersion(version))); + $$""" + class C + { + void M(object o) + { + [|var|] x = o as string; + {{input}} + } + } + """, + $$""" + class C + { + void M(object o) + { + {{output}} + } + } + """, new TestParameters(CSharpParseOptions.Default.WithLanguageVersion(version))); } [Fact] diff --git a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests_FixAllTests.cs index d0694b4842feb..78dcb4aac0d66 100644 --- a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpAsAndNullCheckTests_FixAllTests.cs @@ -19,250 +19,270 @@ public partial class CSharpAsAndNullCheckTests public async Task FixAllInDocument1() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - string a; - {|FixAllInDocument:var|} x = o as string; - if (x != null) - { - } - - var y = o as string; - if (y != null) - { - } - - if ((a = o as string) == null) - { - } - - var c = o as string; - var d = c != null ? 1 : 0; - - var e = o as string; - return e != null ? 1 : 0; - } -}", -@"class C -{ - int M() - { - if (o is string x) - { - } - - if (o is string y) - { - } - - if (!(o is string a)) - { - } - - var d = o is string c ? 1 : 0; - - return o is string e ? 1 : 0; - } -}", parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)); + """ + class C + { + int M() + { + string a; + {|FixAllInDocument:var|} x = o as string; + if (x != null) + { + } + + var y = o as string; + if (y != null) + { + } + + if ((a = o as string) == null) + { + } + + var c = o as string; + var d = c != null ? 1 : 0; + + var e = o as string; + return e != null ? 1 : 0; + } + } + """, + """ + class C + { + int M() + { + if (o is string x) + { + } + + if (o is string y) + { + } + + if (!(o is string a)) + { + } + + var d = o is string c ? 1 : 0; + + return o is string e ? 1 : 0; + } + } + """, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)); } [Fact] public async Task FixAllInDocument1_CSharp9() { await TestInRegularAndScriptAsync( -@"class C -{ - int M() - { - string a; - {|FixAllInDocument:var|} x = o as string; - if (x != null) - { - } - - var y = o as string; - if (y != null) - { - } - - if ((a = o as string) == null) - { - } - - var c = o as string; - var d = c != null ? 1 : 0; - - var e = o as string; - return e != null ? 1 : 0; - } -}", -@"class C -{ - int M() - { - if (o is string x) - { - } - - if (o is string y) - { - } - - if (o is not string a) - { - } - - var d = o is string c ? 1 : 0; - - return o is string e ? 1 : 0; - } -}", parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9)); + """ + class C + { + int M() + { + string a; + {|FixAllInDocument:var|} x = o as string; + if (x != null) + { + } + + var y = o as string; + if (y != null) + { + } + + if ((a = o as string) == null) + { + } + + var c = o as string; + var d = c != null ? 1 : 0; + + var e = o as string; + return e != null ? 1 : 0; + } + } + """, + """ + class C + { + int M() + { + if (o is string x) + { + } + + if (o is string y) + { + } + + if (o is not string a) + { + } + + var d = o is string c ? 1 : 0; + + return o is string e ? 1 : 0; + } + } + """, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9)); } [Fact] public async Task FixAllInDocument2() { await TestInRegularAndScriptAsync( -@"class Symbol -{ - public ContainingSymbol { get; } - - void M(object o, bool b0, bool b1) - { - {|FixAllInDocument:var|} symbol = o as Symbol; - if (symbol != null) - { - while ((object)symbol != null && b1) - { - symbol = symbol.ContainingSymbol as Symbol; - } - - if ((object)symbol == null || b2) - { - throw null; - } - - var use = symbol; - } - } -}", -@"class Symbol -{ - public ContainingSymbol { get; } - - void M(object o, bool b0, bool b1) - { - if (o is Symbol symbol) - { - while ((object)symbol != null && b1) - { - symbol = symbol.ContainingSymbol as Symbol; - } - - if ((object)symbol == null || b2) - { - throw null; - } - - var use = symbol; - } -} -}"); + """ + class Symbol + { + public ContainingSymbol { get; } + + void M(object o, bool b0, bool b1) + { + {|FixAllInDocument:var|} symbol = o as Symbol; + if (symbol != null) + { + while ((object)symbol != null && b1) + { + symbol = symbol.ContainingSymbol as Symbol; + } + + if ((object)symbol == null || b2) + { + throw null; + } + + var use = symbol; + } + } + } + """, + """ + class Symbol + { + public ContainingSymbol { get; } + + void M(object o, bool b0, bool b1) + { + if (o is Symbol symbol) + { + while ((object)symbol != null && b1) + { + symbol = symbol.ContainingSymbol as Symbol; + } + + if ((object)symbol == null || b2) + { + throw null; + } + + var use = symbol; + } + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26679")] public async Task FixAllInDocument3() { await TestInRegularAndScriptAsync( -@"class Test -{ - void M() - { - {|FixAllInDocument:IMethodSymbol|} methodSymbol; - IPropertySymbol propertySymbol; - IEventSymbol eventSymbol; - bool isImplementingExplicitly; - - // Only methods, properties and events can implement an interface member - if ((methodSymbol = memberSymbol as IMethodSymbol) != null) - { - // Check if the member is implementing an interface explicitly - isImplementingExplicitly = methodSymbol.ExplicitInterfaceImplementations.Any(); - } - else if ((propertySymbol = memberSymbol as IPropertySymbol) != null) - { - // Check if the member is implementing an interface explicitly - isImplementingExplicitly = propertySymbol.ExplicitInterfaceImplementations.Any(); - } - else if ((eventSymbol = memberSymbol as IEventSymbol) != null) - { - // Check if the member is implementing an interface explicitly - isImplementingExplicitly = eventSymbol.ExplicitInterfaceImplementations.Any(); - } - else - { - return false; - } - } -}", -@"class Test -{ - void M() - { - bool isImplementingExplicitly; - - // Only methods, properties and events can implement an interface member - if (memberSymbol is IMethodSymbol methodSymbol) - { - // Check if the member is implementing an interface explicitly - isImplementingExplicitly = methodSymbol.ExplicitInterfaceImplementations.Any(); - } - else if (memberSymbol is IPropertySymbol propertySymbol) - { - // Check if the member is implementing an interface explicitly - isImplementingExplicitly = propertySymbol.ExplicitInterfaceImplementations.Any(); - } - else if (memberSymbol is IEventSymbol eventSymbol) - { - // Check if the member is implementing an interface explicitly - isImplementingExplicitly = eventSymbol.ExplicitInterfaceImplementations.Any(); - } - else - { - return false; - } - } -}"); + """ + class Test + { + void M() + { + {|FixAllInDocument:IMethodSymbol|} methodSymbol; + IPropertySymbol propertySymbol; + IEventSymbol eventSymbol; + bool isImplementingExplicitly; + + // Only methods, properties and events can implement an interface member + if ((methodSymbol = memberSymbol as IMethodSymbol) != null) + { + // Check if the member is implementing an interface explicitly + isImplementingExplicitly = methodSymbol.ExplicitInterfaceImplementations.Any(); + } + else if ((propertySymbol = memberSymbol as IPropertySymbol) != null) + { + // Check if the member is implementing an interface explicitly + isImplementingExplicitly = propertySymbol.ExplicitInterfaceImplementations.Any(); + } + else if ((eventSymbol = memberSymbol as IEventSymbol) != null) + { + // Check if the member is implementing an interface explicitly + isImplementingExplicitly = eventSymbol.ExplicitInterfaceImplementations.Any(); + } + else + { + return false; + } + } + } + """, + """ + class Test + { + void M() + { + bool isImplementingExplicitly; + + // Only methods, properties and events can implement an interface member + if (memberSymbol is IMethodSymbol methodSymbol) + { + // Check if the member is implementing an interface explicitly + isImplementingExplicitly = methodSymbol.ExplicitInterfaceImplementations.Any(); + } + else if (memberSymbol is IPropertySymbol propertySymbol) + { + // Check if the member is implementing an interface explicitly + isImplementingExplicitly = propertySymbol.ExplicitInterfaceImplementations.Any(); + } + else if (memberSymbol is IEventSymbol eventSymbol) + { + // Check if the member is implementing an interface explicitly + isImplementingExplicitly = eventSymbol.ExplicitInterfaceImplementations.Any(); + } + else + { + return false; + } + } + } + """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26680")] public async Task FixAllInDocument4() { await TestInRegularAndScriptAsync( -@"class Test -{ - void M() - { - {|FixAllInDocument:var|} firstTextPartSyntax = summaryElement.Content[0] as XmlTextSyntax; - var classReferencePart = summaryElement.Content[1] as XmlEmptyElementSyntax; - var secondTextPartSyntax = summaryElement.Content[2] as XmlTextSyntax; - - if (firstTextPartSyntax != null && classReferencePart != null && secondTextPartSyntax != null) - { - } - } -}", -@"class Test -{ - void M() - { - if (summaryElement.Content[0] is XmlTextSyntax firstTextPartSyntax && summaryElement.Content[1] is XmlEmptyElementSyntax classReferencePart && summaryElement.Content[2] is XmlTextSyntax secondTextPartSyntax) - { - } - } -}"); + """ + class Test + { + void M() + { + {|FixAllInDocument:var|} firstTextPartSyntax = summaryElement.Content[0] as XmlTextSyntax; + var classReferencePart = summaryElement.Content[1] as XmlEmptyElementSyntax; + var secondTextPartSyntax = summaryElement.Content[2] as XmlTextSyntax; + + if (firstTextPartSyntax != null && classReferencePart != null && secondTextPartSyntax != null) + { + } + } + } + """, + """ + class Test + { + void M() + { + if (summaryElement.Content[0] is XmlTextSyntax firstTextPartSyntax && summaryElement.Content[1] is XmlEmptyElementSyntax classReferencePart && summaryElement.Content[2] is XmlTextSyntax secondTextPartSyntax) + { + } + } + } + """); } } } diff --git a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzerTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzerTests_FixAllTests.cs index 51c1ad8322098..a2cf105574655 100644 --- a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzerTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzerTests_FixAllTests.cs @@ -17,68 +17,76 @@ public partial class CSharpIsAndCastCheckDiagnosticAnalyzerTests public async Task FixAllInDocument1() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - if (x is string) - { - {|FixAllInDocument:var|} v1 = (string)x; - } + """ + class C + { + void M() + { + if (x is string) + { + {|FixAllInDocument:var|} v1 = (string)x; + } - if (x is bool) - { - var v2 = (bool)x; - } - } -}", -@"class C -{ - void M() - { - if (x is string v1) - { - } + if (x is bool) + { + var v2 = (bool)x; + } + } + } + """, + """ + class C + { + void M() + { + if (x is string v1) + { + } - if (x is bool v2) - { - } - } -}"); + if (x is bool v2) + { + } + } + } + """); } [Fact] public async Task FixAllInDocument2() { await TestInRegularAndScriptAsync( -@"class C -{ - void M() - { - if (x is string) - { - var v1 = (string)x; - } + """ + class C + { + void M() + { + if (x is string) + { + var v1 = (string)x; + } - if (x is bool) - { - {|FixAllInDocument:var|} v2 = (bool)x; - } - } -}", -@"class C -{ - void M() - { - if (x is string v1) - { - } + if (x is bool) + { + {|FixAllInDocument:var|} v2 = (bool)x; + } + } + } + """, + """ + class C + { + void M() + { + if (x is string v1) + { + } - if (x is bool v2) - { - } - } -}"); + if (x is bool v2) + { + } + } + } + """); } } } diff --git a/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests_FixAllTests.cs b/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests_FixAllTests.cs index ae6921fc44b95..fb008d28892bb 100644 --- a/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests_FixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/UseThrowExpression/UseThrowExpressionTests_FixAllTests.cs @@ -18,285 +18,309 @@ public partial class UseThrowExpressionTests public async Task FixAllInDocument1() { await TestInRegularAndScriptAsync( -@"using System; - -class C -{ - void M(string s, string t) - { - if (s == null) - { - {|FixAllInDocument:throw|} new ArgumentNullException(nameof(s)); - } - - if (t == null) - { - throw new ArgumentNullException(nameof(t)); - } - - _s = s; - _t = t; - } -}", -@"using System; - -class C -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - _t = t ?? throw new ArgumentNullException(nameof(t)); - } -}"); + """ + using System; + + class C + { + void M(string s, string t) + { + if (s == null) + { + {|FixAllInDocument:throw|} new ArgumentNullException(nameof(s)); + } + + if (t == null) + { + throw new ArgumentNullException(nameof(t)); + } + + _s = s; + _t = t; + } + } + """, + """ + using System; + + class C + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + _t = t ?? throw new ArgumentNullException(nameof(t)); + } + } + """); } [Fact] public async Task FixAllInDocument2() { await TestInRegularAndScriptAsync( -@"using System; - -class C -{ - void M(string s, string t) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - if (t == null) - { - {|FixAllInDocument:throw|} new ArgumentNullException(nameof(t)); - } - - _s = s; - _t = t; - } -}", -@"using System; - -class C -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - _t = t ?? throw new ArgumentNullException(nameof(t)); - } -}"); + """ + using System; + + class C + { + void M(string s, string t) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + if (t == null) + { + {|FixAllInDocument:throw|} new ArgumentNullException(nameof(t)); + } + + _s = s; + _t = t; + } + } + """, + """ + using System; + + class C + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + _t = t ?? throw new ArgumentNullException(nameof(t)); + } + } + """); } [Fact] public async Task FixAllInDocument3() { await TestInRegularAndScriptAsync( -@"using System; - -class C -{ - void M(string s, string t) - { - if (s == null) - { - {|FixAllInDocument:throw new ArgumentNullException(nameof(s));|} - } - - if (t == null) - { - throw new ArgumentNullException(nameof(t)); - } - - _s = s; - _t = t; - } -}", -@"using System; - -class C -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - _t = t ?? throw new ArgumentNullException(nameof(t)); - } -}"); + """ + using System; + + class C + { + void M(string s, string t) + { + if (s == null) + { + {|FixAllInDocument:throw new ArgumentNullException(nameof(s));|} + } + + if (t == null) + { + throw new ArgumentNullException(nameof(t)); + } + + _s = s; + _t = t; + } + } + """, + """ + using System; + + class C + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + _t = t ?? throw new ArgumentNullException(nameof(t)); + } + } + """); } [Fact] public async Task FixAllInDocument4() { await TestInRegularAndScriptAsync( -@"using System; - -class C -{ - void M(string s, string t) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - if (t == null) - { - {|FixAllInDocument:throw new ArgumentNullException(nameof(t));|} - } - - _s = s; - _t = t; - } -}", -@"using System; - -class C -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - _t = t ?? throw new ArgumentNullException(nameof(t)); - } -}"); + """ + using System; + + class C + { + void M(string s, string t) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + if (t == null) + { + {|FixAllInDocument:throw new ArgumentNullException(nameof(t));|} + } + + _s = s; + _t = t; + } + } + """, + """ + using System; + + class C + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + _t = t ?? throw new ArgumentNullException(nameof(t)); + } + } + """); } [Fact] public async Task FixAllInDocumentDoNotTouchOtherDocuments() { await TestInRegularAndScriptAsync( -@" - - -using System; - -class C -{ - void M(string s, string t) - { - if (s == null) - { - {|FixAllInDocument:throw|} new ArgumentNullException(nameof(s)); - } - - _s = s; - } -} - - -using System; - -class D -{ - void M(string s, string t) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - _s = s; - } -} - - -", -@" - - -using System; - -class C -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - } -} - - -using System; - -class D -{ - void M(string s, string t) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - _s = s; - } -} - - -"); + """ + + + + using System; + + class C + { + void M(string s, string t) + { + if (s == null) + { + {|FixAllInDocument:throw|} new ArgumentNullException(nameof(s)); + } + + _s = s; + } + } + + + using System; + + class D + { + void M(string s, string t) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + _s = s; + } + } + + + + """, + """ + + + + using System; + + class C + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + } + } + + + using System; + + class D + { + void M(string s, string t) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + _s = s; + } + } + + + + """); } [Fact] public async Task FixAllInProject1() { await TestInRegularAndScriptAsync( -@" - - -using System; - -class C -{ - void M(string s, string t) - { - if (s == null) - { - {|FixAllInProject:throw|} new ArgumentNullException(nameof(s)); - } - - _s = s; - } -} - - -using System; - -class D -{ - void M(string s, string t) - { - if (s == null) - { - throw new ArgumentNullException(nameof(s)); - } - - _s = s; - } -} - - -", -@" - - -using System; - -class C -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - } -} - - -using System; - -class D -{ - void M(string s, string t) - { - _s = s ?? throw new ArgumentNullException(nameof(s)); - } -} - - -"); + """ + + + + using System; + + class C + { + void M(string s, string t) + { + if (s == null) + { + {|FixAllInProject:throw|} new ArgumentNullException(nameof(s)); + } + + _s = s; + } + } + + + using System; + + class D + { + void M(string s, string t) + { + if (s == null) + { + throw new ArgumentNullException(nameof(s)); + } + + _s = s; + } + } + + + + """, + """ + + + + using System; + + class C + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + } + } + + + using System; + + class D + { + void M(string s, string t) + { + _s = s ?? throw new ArgumentNullException(nameof(s)); + } + } + + + + """); } } } diff --git a/src/Analyzers/CSharp/Tests/UseUtf8StringLiteral/UseUtf8StringLiteralTests.cs b/src/Analyzers/CSharp/Tests/UseUtf8StringLiteral/UseUtf8StringLiteralTests.cs index 78a404efe7b2f..35089cb310bc0 100644 --- a/src/Analyzers/CSharp/Tests/UseUtf8StringLiteral/UseUtf8StringLiteralTests.cs +++ b/src/Analyzers/CSharp/Tests/UseUtf8StringLiteral/UseUtf8StringLiteralTests.cs @@ -824,12 +824,12 @@ public async Task TestInvalidUtf8Strings(byte[] bytes) await new VerifyCS.Test { TestCode = -$@" -public class C -{{ - private static readonly byte[] _bytes = new byte[] {{ {string.Join(", ", bytes)} }}; -}} -", + $$""" + public class C + { + private static readonly byte[] _bytes = new byte[] { {{string.Join(", ", bytes)}} }; + } + """, CodeActionValidationMode = CodeActionValidationMode.None, ReferenceAssemblies = ReferenceAssemblies.Net.Net60, LanguageVersion = LanguageVersion.CSharp12 diff --git a/src/Analyzers/CSharp/Tests/ValidateFormatString/ValidateFormatStringTests.cs b/src/Analyzers/CSharp/Tests/ValidateFormatString/ValidateFormatStringTests.cs index 5fa7b78da366b..b0974fa0e23ad 100644 --- a/src/Analyzers/CSharp/Tests/ValidateFormatString/ValidateFormatStringTests.cs +++ b/src/Analyzers/CSharp/Tests/ValidateFormatString/ValidateFormatStringTests.cs @@ -625,13 +625,15 @@ static void Main(string[] args) [Fact] public async Task TestOption_Ignored() { - var source = @"class Program -{ - static void Main(string[] args) - { - string.Format(""This [|{1}|] is my test"", ""teststring1""); - } -}"; + var source = """ + class Program + { + static void Main(string[] args) + { + string.Format("This [|{1}|] is my test", "teststring1"); + } + } + """; await TestDiagnosticInfoAsync( source, options: null, diff --git a/src/Analyzers/Core/Analyzers/PopulateSwitch/AbstractPopulateSwitchDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/PopulateSwitch/AbstractPopulateSwitchDiagnosticAnalyzer.cs index 9b165daa31d81..8dc3734753371 100644 --- a/src/Analyzers/Core/Analyzers/PopulateSwitch/AbstractPopulateSwitchDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/PopulateSwitch/AbstractPopulateSwitchDiagnosticAnalyzer.cs @@ -67,7 +67,7 @@ private void AnalyzeOperation(OperationAnalysisContext context) Descriptor, GetDiagnosticLocation(switchBlock), properties: properties, - additionalLocations: new[] { switchBlock.GetLocation() }); + additionalLocations: [switchBlock.GetLocation()]); context.ReportDiagnostic(diagnostic); } } diff --git a/src/Analyzers/Core/Analyzers/RemoveRedundantEquality/AbstractRemoveRedundantEqualityDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveRedundantEquality/AbstractRemoveRedundantEqualityDiagnosticAnalyzer.cs index 0bd6ce7c0cbb4..3aa18b1e4f3da 100644 --- a/src/Analyzers/Core/Analyzers/RemoveRedundantEquality/AbstractRemoveRedundantEqualityDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveRedundantEquality/AbstractRemoveRedundantEqualityDiagnosticAnalyzer.cs @@ -82,7 +82,7 @@ private void AnalyzeBinaryOperator(OperationAnalysisContext context) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, operatorToken.GetLocation(), - additionalLocations: new[] { operation.Syntax.GetLocation() }, + additionalLocations: [operation.Syntax.GetLocation()], properties: properties.ToImmutable())); } diff --git a/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs index 16d164ee246e2..0d3f0fc8f7293 100644 --- a/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs @@ -93,7 +93,7 @@ protected AbstractUseCollectionInitializerDiagnosticAnalyzer() protected abstract bool AreCollectionInitializersSupported(Compilation compilation); protected abstract bool AreCollectionExpressionsSupported(Compilation compilation); protected abstract bool CanUseCollectionExpression( - SemanticModel semanticModel, TObjectCreationExpressionSyntax objectCreationExpression, INamedTypeSymbol? expressionType, bool allowInterfaceConversion, CancellationToken cancellationToken, out bool changesSemantics); + SemanticModel semanticModel, TObjectCreationExpressionSyntax objectCreationExpression, INamedTypeSymbol? expressionType, bool allowSemanticsChange, CancellationToken cancellationToken, out bool changesSemantics); protected abstract TAnalyzer GetAnalyzer(); @@ -237,8 +237,8 @@ private void AnalyzeNode( return null; // Check if it would actually be legal to use a collection expression here though. - var allowInterfaceConversion = preferExpressionOption.Value == CollectionExpressionPreference.WhenTypesLooselyMatch; - if (!CanUseCollectionExpression(semanticModel, objectCreationExpression, expressionType, allowInterfaceConversion, cancellationToken, out var changesSemantics)) + var allowSemanticsChange = preferExpressionOption.Value == CollectionExpressionPreference.WhenTypesLooselyMatch; + if (!CanUseCollectionExpression(semanticModel, objectCreationExpression, expressionType, allowSemanticsChange, cancellationToken, out var changesSemantics)) return null; return (matches, shouldUseCollectionExpression: true, changesSemantics); diff --git a/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs index 83ab319eaa162..fe0643d9799a7 100644 --- a/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs @@ -25,7 +25,7 @@ protected AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer( protected sealed override CodeStyleOption2 GetStylePreference(OperationAnalysisContext context) => context.GetAnalyzerOptions().PreferConditionalExpressionOverReturn; - protected override (bool matched, bool canSimplify) TryMatchPattern(IConditionalOperation ifOperation, ISymbol containingSymbol) + protected sealed override (bool matched, bool canSimplify) TryMatchPattern(IConditionalOperation ifOperation, ISymbol containingSymbol) { if (!UseConditionalExpressionForReturnHelpers.TryMatchPattern( GetSyntaxFacts(), ifOperation, containingSymbol, out var isRef, out var trueStatement, out var falseStatement, out var trueReturn, out var falseReturn)) @@ -33,6 +33,12 @@ protected override (bool matched, bool canSimplify) TryMatchPattern(IConditional return default; } + if (!IsStatementSupported(trueStatement) || + !IsStatementSupported(falseStatement)) + { + return default; + } + var canSimplify = UseConditionalExpressionHelpers.CanSimplify( trueReturn?.ReturnedValue ?? trueStatement, falseReturn?.ReturnedValue ?? falseStatement, @@ -41,5 +47,8 @@ protected override (bool matched, bool canSimplify) TryMatchPattern(IConditional return (matched: true, canSimplify); } + + protected virtual bool IsStatementSupported(IOperation statement) + => true; } } diff --git a/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs index 7b90e7aecb28c..9ae7ad8d620ba 100644 --- a/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs @@ -80,7 +80,7 @@ private void AnalyzeOperationBlock(HashCodeAnalyzer analyzer, OperationBlockAnal Descriptor, diagnosticLocation, option.Notification, - new[] { operationLocation, declarationLocation }, + [operationLocation, declarationLocation], ImmutableDictionary.Empty)); } } diff --git a/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs index 8fe0a1960550f..a822e00a760ff 100644 --- a/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs @@ -69,13 +69,13 @@ protected sealed override TSwitchSyntax InsertSwitchArms(SyntaxGenerator generat => (TSwitchSyntax)generator.InsertSwitchSections(switchNode, insertLocation, newArms); protected sealed override TSwitchArmSyntax CreateDefaultSwitchArm(SyntaxGenerator generator, Compilation compilation) - => (TSwitchArmSyntax)generator.DefaultSwitchSection(new[] { generator.ExitSwitchStatement() }); + => (TSwitchArmSyntax)generator.DefaultSwitchSection([generator.ExitSwitchStatement()]); protected sealed override TSwitchArmSyntax CreateSwitchArm(SyntaxGenerator generator, Compilation compilation, TMemberAccessExpression caseLabel) - => (TSwitchArmSyntax)generator.SwitchSection(caseLabel, new[] { generator.ExitSwitchStatement() }); + => (TSwitchArmSyntax)generator.SwitchSection(caseLabel, [generator.ExitSwitchStatement()]); protected override TSwitchArmSyntax CreateNullSwitchArm(SyntaxGenerator generator, Compilation compilation) - => (TSwitchArmSyntax)generator.SwitchSection(generator.NullLiteralExpression(), new[] { generator.ExitSwitchStatement() }); + => (TSwitchArmSyntax)generator.SwitchSection(generator.NullLiteralExpression(), [generator.ExitSwitchStatement()]); protected sealed override int InsertPosition(ISwitchOperation switchStatement) { diff --git a/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb index 282b82a1cdd60..b15c4bf2bd948 100644 --- a/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb @@ -38,7 +38,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseCollectionInitializer Return False End Function - Protected Overrides Function CanUseCollectionExpression(semanticModel As SemanticModel, objectCreationExpression As ObjectCreationExpressionSyntax, expressionType As INamedTypeSymbol, allowInterfaceConversion As Boolean, cancellationToken As CancellationToken, ByRef changesSemantics As Boolean) As Boolean + Protected Overrides Function CanUseCollectionExpression(semanticModel As SemanticModel, objectCreationExpression As ObjectCreationExpressionSyntax, expressionType As INamedTypeSymbol, allowSemanticsChange As Boolean, cancellationToken As CancellationToken, ByRef changesSemantics As Boolean) As Boolean Throw ExceptionUtilities.Unreachable() End Function End Class diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf index 47a542199ee41..930534b1625a1 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.cs.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + Odebrat nepotřebné importy diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf index 522fc10f1e955..f4920dcf4e76e 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.fr.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + Supprimer les importations inutiles diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf index fdb0ad2c50d16..35aebed806bc5 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.ja.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + 不要なインポートの削除 diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf index 0c91f9ff18b26..94e2446155d19 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pl.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + Usuń niepotrzebne importy diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf index ea507ec111ac3..5dfa2a78a4de9 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.pt-BR.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + Remover as Importações desnecessárias diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf index caee330ec530d..c37b1a1d9b70f 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.tr.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + Gereksiz içeri aktarmaları kaldır diff --git a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf index 845122cc4ded6..db0683a18cc6e 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf +++ b/src/Analyzers/VisualBasic/CodeFixes/xlf/VisualBasicCodeFixesResources.zh-Hant.xlf @@ -44,7 +44,7 @@ Remove unnecessary imports - Remove unnecessary imports + 移除不必要的 Import diff --git a/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb b/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb index 2ca647be09610..773f7bd79adcc 100644 --- a/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb +++ b/src/Analyzers/VisualBasic/Tests/RemoveUnnecessaryCast/RemoveUnnecessaryCastTests.vb @@ -934,6 +934,23 @@ End Module Await TestMissingAsync(markup) End Function + + Public Async Function TestDoNotRemoveNecessaryCastPassedToIllegalParamArray() As Task + Dim markup = + +Module M + Sub Main() + Goo([|CObj(Nothing)|]) + End Sub + Sub Goo(ParamArray x As Object) + Console.WriteLine(x.Length) + End Sub +End Module + + + Await TestMissingAsync(markup) + End Function + Public Async Function TestRemoveUnnecessaryCastPassedToParamArray1() As Task Dim markup = diff --git a/src/Compilers/.editorconfig b/src/Compilers/.editorconfig index 219639f810017..3852b7712473b 100644 --- a/src/Compilers/.editorconfig +++ b/src/Compilers/.editorconfig @@ -25,6 +25,10 @@ csharp_style_var_when_type_is_apparent = true:none csharp_style_var_elsewhere = false:none csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +# RS0062: Do not capture primary constructor parameters +# Warning so that it doesn't block local F5, but will fail in CI with WarnAsError +dotnet_diagnostic.RS0062.severity = warning + # XML files [*.xml] indent_size = 2 diff --git a/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs b/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs index 13e97132b18c4..910282106a46a 100644 --- a/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs +++ b/src/Compilers/CSharp/Portable/Binder/BinderFactory.BinderFactoryVisitor.cs @@ -1220,8 +1220,9 @@ private Binder GetParameterNameAttributeValueBinder(MemberDeclarationSyntax memb return new WithParametersBinder(method.Parameters, nextBinder); } - if (memberSyntax is TypeDeclarationSyntax { ParameterList: { ParameterCount: > 0 } }) + if (memberSyntax is TypeDeclarationSyntax { ParameterList: { ParameterCount: > 0 } } typeDeclaration) { + _ = typeDeclaration.ParameterList; Binder outerBinder = VisitCore(memberSyntax); SourceNamedTypeSymbol type = ((NamespaceOrTypeSymbol)outerBinder.ContainingMemberOrLambda).GetSourceTypeMember((TypeDeclarationSyntax)memberSyntax); var primaryConstructor = type.PrimaryConstructor; diff --git a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs index 5bb0aa29ba59d..9fb7f496e7fad 100644 --- a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs +++ b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs @@ -1692,7 +1692,7 @@ string dumpStateForCase(StateForCase cd) { builder.Append(" BIND["); builder.Append(string.Join("; ", bindings)); - builder.Append("]"); + builder.Append(']'); } if (cd.WhenClause is { }) diff --git a/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs b/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs index 3eb2cec8b9530..c25c2bb35ecbb 100644 --- a/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs +++ b/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs @@ -550,7 +550,7 @@ string tryHandleRecursivePattern(ref bool unnamedEnumValue) subpatternBuilder.Append(", "); subpatternBuilder.Append(newPattern); } - subpatternBuilder.Append(")"); + subpatternBuilder.Append(')'); var result = subpatternBuilder.ToString(); if (deconstruction != null && needsPropertyString) { diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index 017fc652b6222..7b1123a3c62c7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -358,7 +358,7 @@ internal string Dump() sb.Append(_formalParameterTypes[i]); } - sb.Append("\n"); + sb.Append('\n'); sb.AppendFormat("Argument types ({0})\n", string.Join(", ", from a in _arguments select a.Type)); @@ -377,16 +377,16 @@ internal string Dump() switch (_dependencies[i, j]) { case Dependency.NotDependent: - sb.Append("N"); + sb.Append('N'); break; case Dependency.Direct: - sb.Append("D"); + sb.Append('D'); break; case Dependency.Indirect: - sb.Append("I"); + sb.Append('I'); break; case Dependency.Unknown: - sb.Append("U"); + sb.Append('U'); break; } } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 510a987660dd9..e4277a694aaa3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -4151,11 +4151,7 @@ private Conversion CheckArgumentForApplicability( // exists from the argument to the type of the corresponding parameter, or // - for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter. - // effective RefKind has to match unless argument expression is of the type dynamic. - // This is a bug in Dev11 which we also implement. - // The spec is correct, this is not an intended behavior. We don't fix the bug to avoid a breaking change. - if (!(argRefKind == parRefKind || - (argRefKind == RefKind.None && argument.HasDynamicType()))) + if (argRefKind != parRefKind) { return Conversion.NoConversion; } diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs index 97a3154e0ecba..8a489265541c9 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs @@ -52,9 +52,15 @@ public static void AddToMap(BoundNode root, Dictionary sourceToMetadata; + public override SymbolMatcher SourceToMetadataSymbolMatcher { get; } = sourceToMetadata; public override SymbolMatcher SourceToPreviousSymbolMatcher => _sourceToPrevious; - public override SymbolMatcher PreviousSourceToMetadataSymbolMatcher => previousSourceToMetadata; + public override SymbolMatcher PreviousSourceToMetadataSymbolMatcher { get; } = previousSourceToMetadata; protected override ISymbolInternal? GetISymbolInternalOrNull(ISymbol symbol) { @@ -121,17 +122,17 @@ protected override ImmutableArray GetLocalSlotMapFromMetadata(Stan { Debug.Assert(!handle.IsNil); - var localInfos = metadataDecoder.GetLocalsOrThrow(handle); + var localInfos = _metadataDecoder.GetLocalsOrThrow(handle); var result = CreateLocalSlotMap(debugInfo, localInfos); Debug.Assert(result.Length == localInfos.Length); return result; } protected override ITypeSymbolInternal? TryGetStateMachineType(MethodDefinitionHandle methodHandle) - => metadataDecoder.Module.HasStateMachineAttribute(methodHandle, out var typeName) ? metadataDecoder.GetTypeSymbolForSerializedType(typeName) : null; + => _metadataDecoder.Module.HasStateMachineAttribute(methodHandle, out var typeName) ? _metadataDecoder.GetTypeSymbolForSerializedType(typeName) : null; protected override IMethodSymbolInternal GetMethodSymbol(MethodDefinitionHandle methodHandle) - => (IMethodSymbolInternal)metadataDecoder.GetSymbolForILToken(methodHandle); + => (IMethodSymbolInternal)_metadataDecoder.GetSymbolForILToken(methodHandle); /// /// Match local declarations to names to generate a map from diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/ExpandedVarargsMethodReference.cs b/src/Compilers/CSharp/Portable/Emitter/Model/ExpandedVarargsMethodReference.cs index 6ae0d24286745..5902f478f2db2 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/ExpandedVarargsMethodReference.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/ExpandedVarargsMethodReference.cs @@ -201,7 +201,7 @@ public override string ToString() Append(result, p.GetType(new EmitContext())); } - result.Builder.Append(")"); + result.Builder.Append(')'); return result.ToStringAndFree(); } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs index 0d7f4f90d026d..61fb94f56681f 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs @@ -252,7 +252,7 @@ protected string DumpLabels() result.Append(name).Append(": ").Append(this.Dump(_labels[key])); first = false; } - result.Append("}"); + result.Append('}'); return result.ToString(); } #endif diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass_LocalFunctions.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass_LocalFunctions.cs index 0b626f3a4e038..ca468e82e76c2 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass_LocalFunctions.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass_LocalFunctions.cs @@ -56,6 +56,11 @@ protected TLocalFunctionState GetOrCreateLocalFuncUsages(LocalFunctionSymbol loc return usages; } + protected bool HasLocalFuncUsagesCreated(LocalFunctionSymbol localFunc) + { + return _localFuncVarUsages?.ContainsKey(localFunc) == true; + } + public override BoundNode? VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc) { if (localFunc.Symbol.IsExtern) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index eeefb8ac43b57..90abbd1cc148c 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -2774,7 +2774,7 @@ protected override string Dump(LocalState state) var builder = new StringBuilder(); builder.Append("[assigned "); AppendBitNames(state.Assigned, builder); - builder.Append("]"); + builder.Append(']'); return builder.ToString(); } @@ -2795,7 +2795,7 @@ protected void AppendBitName(int bit, StringBuilder builder) if (id.ContainingSlot > 0) { AppendBitName(id.ContainingSlot, builder); - builder.Append("."); + builder.Append('.'); } builder.Append( diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 51144fbfcdf5a..2168fd1fdf6f4 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -3023,26 +3023,80 @@ private void VisitStatementsWithLocalFunctions(BoundBlock block) // local function, and then a pass where we visit the local functions. If there's no // recursion or calls between the local functions, the starting state of the local // function should be stable and we don't need a second pass. - if (!TrackingRegions && !block.LocalFunctions.IsDefaultOrEmpty) + if (!block.LocalFunctions.IsDefaultOrEmpty) { + Debug.Assert(!TrackingRegions); + // First visit everything else + var localFuncs = ArrayBuilder.GetInstance(); foreach (var stmt in block.Statements) { - if (stmt.Kind != BoundKind.LocalFunctionStatement) + if (stmt is BoundLocalFunctionStatement localFunc) + { + localFuncs.Add(localFunc); + } + else { VisitStatement(stmt); } } - // Now visit the local function bodies - foreach (var stmt in block.Statements) + // Visited local functions will be set to null. + // We keep count of unvisited (non-null) local functions. + var unvisitedLocalFuncs = localFuncs.Count; + + // Now visit the local function bodies. + // We first visit those we have seen called (hence we know their starting state), + // repeating this while visiting new bodies (which might contain more call sites). + // This avoids unnecessary passes and incorrect starting states of reachable bodies + // (which could be captured in loop head state for example). + for (bool newBodiesVisited = true; newBodiesVisited;) { - if (stmt is BoundLocalFunctionStatement localFunc) + newBodiesVisited = false; + + for (int i = 0; unvisitedLocalFuncs != 0 && i < localFuncs.Count; i++) { - TakeIncrementalSnapshot(localFunc); - VisitLocalFunctionStatement(localFunc); + // We visit the body only if the function's usages state has been created + // which happens when we visit the function's call site or its body. + // In the first pass of the nullable walker, existence of usages here means that a call site has been visited. + // In subsequent nullable walker passes, the starting state is preserved from previous passes. + // In any case, existence of usages means that we have a good starting state. + if (localFuncs[i] is { } localFunc && HasLocalFuncUsagesCreated(localFunc.Symbol)) + { + localFuncs[i] = null; + unvisitedLocalFuncs--; + + // The body of this local function might contain calls to other local functions, + // hence we will rerun the outer loop to visit bodies of newly-called functions if any. + newBodiesVisited = true; + + TakeIncrementalSnapshot(localFunc); + VisitLocalFunctionStatement(localFunc); + } + } + + // If we haven't visited new bodies in this iteration, visit an unreachable function if any. + // This might make other functions reachable, so we will continue with the outer loop. + if (!newBodiesVisited && unvisitedLocalFuncs != 0) + { + for (int i = 0; i < localFuncs.Count; i++) + { + if (localFuncs[i] is { } localFunc) + { + localFuncs[i] = null; + unvisitedLocalFuncs--; + newBodiesVisited = true; + TakeIncrementalSnapshot(localFunc); + VisitLocalFunctionStatement(localFunc); + break; + } + } + + Debug.Assert(newBodiesVisited); } } + + localFuncs.Free(); } else { @@ -3056,25 +3110,54 @@ private void VisitStatementsWithLocalFunctions(BoundBlock block) public override BoundNode? VisitLocalFunctionStatement(BoundLocalFunctionStatement node) { var localFunc = node.Symbol; + + // Usages state is created when we visit the function's call site or its body. + // In the first pass of the nullable walker, existence of usages here means that a call site has been visited. + // In subsequent nullable walker passes, the starting state is preserved from previous passes. + // In any case, existence of usages means that we have a good starting state. + var hasGoodStartingState = HasLocalFuncUsagesCreated(localFunc); + var localFunctionState = GetOrCreateLocalFuncUsages(localFunc); - // The starting state (`state`) is the top state ("maybe null"). + // The state for the function's body analysis starts as the top state ("maybe null"). var state = TopState(); - // Captured variables are joined with the state - // at all the local function use sites (`localFunctionState.StartingState`) - // which starts as the bottom state ("not null"). - var startingState = localFunctionState.StartingState; - startingState.ForEach( - (slot, variables) => - { - var symbol = variables[variables.RootSlot(slot)].Symbol; - if (Symbol.IsCaptured(symbol, localFunc)) + if (!hasGoodStartingState) + { + // For unreachable local functions, top-level captured variables are set to "not null", + // ignoring nested slots to avoid depending on slot allocation order + // (e.g., whether we have seen a class field or not already). + state.Normalize(this, _variables); + state.ForEach( + (slot, variables) => { - SetState(ref state, slot, GetState(ref startingState, slot)); - } - }, - _variables); + if (Symbol.IsCaptured(variables[slot].Symbol, localFunc)) + { + SetState(ref state, slot, NullableFlowState.NotNull); + } + }, + _variables); + + // In subsequent passes, we will use the starting state, + // so make sure it's set correctly for unreachable functions from now on. + localFunctionState.StartingState = state.Clone(); + } + else + { + // Captured variables are joined with the state + // from visited call sites of the local function. + var startingState = localFunctionState.StartingState; + startingState.ForEach( + (slot, variables) => + { + var symbol = variables[variables.RootSlot(slot)].Symbol; + if (Symbol.IsCaptured(symbol, localFunc)) + { + SetState(ref state, slot, GetState(ref startingState, slot)); + } + }, + _variables); + } localFunctionState.Visited = true; @@ -12214,7 +12297,7 @@ internal string GetDebuggerDisplay() { var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; - builder.Append(" "); + builder.Append(' '); int n = Math.Min(Capacity, 8); for (int i = n - 1; i >= 0; i--) { @@ -12276,8 +12359,10 @@ internal sealed class LocalFunctionState : AbstractLocalFunctionState /// produce diagnostics and determine types. /// public LocalState StartingState; + public LocalFunctionState(LocalState unreachableState) - : base(unreachableState.Clone(), unreachableState.Clone()) + // Note: these states are not used in nullable analysis. + : base(stateFromBottom: unreachableState.Clone(), stateFromTop: unreachableState.Clone()) { StartingState = unreachableState; } @@ -12287,7 +12372,7 @@ protected override LocalFunctionState CreateLocalFunctionState(LocalFunctionSymb { var variables = (symbol.ContainingSymbol is MethodSymbol containingMethod ? _variables.GetVariablesForMethodScope(containingMethod) : null) ?? _variables.GetRootScope(); - return new LocalFunctionState(LocalState.ReachableStateWithNotNulls(variables)); + return new LocalFunctionState(LocalState.UnreachableState(variables)); } private sealed class NullabilityInfoTypeComparer : IEqualityComparer<(NullabilityInfo info, TypeSymbol? type)> diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringConcat.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringConcat.cs index 62ac0d538b0b0..9dbcb2383016a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringConcat.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringConcat.cs @@ -46,8 +46,8 @@ private BoundExpression RewriteStringConcatenation(SyntaxNode syntax, BinaryOper } // Convert both sides to a string (calling ToString if necessary) - loweredLeft = ConvertConcatExprToString(syntax, loweredLeft); - loweredRight = ConvertConcatExprToString(syntax, loweredRight); + loweredLeft = ConvertConcatExprToString(loweredLeft); + loweredRight = ConvertConcatExprToString(loweredRight); Debug.Assert(loweredLeft.Type is { } && (loweredLeft.Type.IsStringType() || loweredLeft.Type.IsErrorType()) || loweredLeft.ConstantValueOpt?.IsNull == true); Debug.Assert(loweredRight.Type is { } && (loweredRight.Type.IsStringType() || loweredRight.Type.IsErrorType()) || loweredRight.ConstantValueOpt?.IsNull == true); @@ -366,8 +366,10 @@ private BoundExpression RewriteStringConcatInExpressionLambda(SyntaxNode syntax, /// Returns an expression which converts the given expression into a string (or null). /// If necessary, this invokes .ToString() on the expression, to avoid boxing value types. /// - private BoundExpression ConvertConcatExprToString(SyntaxNode syntax, BoundExpression expr) + private BoundExpression ConvertConcatExprToString(BoundExpression expr) { + var syntax = expr.Syntax; + // If it's a value type, it'll have been boxed by the +(string, object) or +(object, string) // operator. Undo that. if (expr.Kind == BoundKind.Conversion) @@ -431,7 +433,7 @@ private BoundExpression ConvertConcatExprToString(SyntaxNode syntax, BoundExpres // types to all special value types. if (structToStringMethod != null && (expr.Type.SpecialType != SpecialType.None && !isFieldOfMarshalByRef(expr, _compilation))) { - return BoundCall.Synthesized(expr.Syntax, expr, initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown, structToStringMethod); + return BoundCall.Synthesized(syntax, expr, initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown, structToStringMethod); } // - It's a reference type (excluding unconstrained generics): no copy @@ -454,9 +456,9 @@ private BoundExpression ConvertConcatExprToString(SyntaxNode syntax, BoundExpres { if (!callWithoutCopy) { - expr = new BoundPassByCopy(expr.Syntax, expr, expr.Type); + expr = new BoundPassByCopy(syntax, expr, expr.Type); } - return BoundCall.Synthesized(expr.Syntax, expr, initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown, objectToStringMethod); + return BoundCall.Synthesized(syntax, expr, initialBindingReceiverIsSubjectToCloning: ThreeState.Unknown, objectToStringMethod); } if (callWithoutCopy) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 2812301df9f58..830d75daae40f 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -12367,7 +12367,7 @@ private InitializerExpressionSyntax ParseObjectOrCollectionInitializer() SkipBadInitializerListTokens, allowTrailingSeparator: true, requireOneElement: false, - allowSemicolonAsSeparator: false); + allowSemicolonAsSeparator: true); var kind = isObjectInitializer(initializers) ? SyntaxKind.ObjectInitializerExpression : SyntaxKind.CollectionInitializerExpression; diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 468b6dea2fc3b..e9b3e9a56cb83 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -570,62 +570,62 @@ private SwitchExpressionSyntax ParseSwitchExpression(ExpressionSyntax governingE governingExpression, switchKeyword, this.EatToken(SyntaxKind.OpenBraceToken), - this.ParseSwitchExpressionArms(), + parseSwitchExpressionArms(), this.EatToken(SyntaxKind.CloseBraceToken)); - } - - private SeparatedSyntaxList ParseSwitchExpressionArms() - { - var arms = _pool.AllocateSeparated(); - while (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken) + SeparatedSyntaxList parseSwitchExpressionArms() { - // Help out in the case where a user is converting a switch statement to a switch expression. Note: - // `default(...)` and `default` will also be consumed as a legal syntactic patterns (though the latter - // will fail during binding). So if the user has `default:` we will recover fine as we handle the - // errant colon below. - var errantCase = this.CurrentToken.Kind == SyntaxKind.CaseKeyword - ? AddError(this.EatToken(), ErrorCode.ERR_BadCaseInSwitchArm) - : null; - - var savedState = _termState; - _termState |= TerminatorState.IsPatternInSwitchExpressionArm; - var pattern = ParsePattern(Precedence.Coalescing, whenIsKeyword: true); - _termState = savedState; - - if (errantCase != null) - pattern = AddLeadingSkippedSyntax(pattern, errantCase); - - // We use a precedence that excludes lambdas, assignments, and a conditional which could have a - // lambda on the right, because we need the parser to leave the EqualsGreaterThanToken - // to be consumed by the switch arm. The strange side-effect of that is that the conditional - // expression is not permitted as a constant expression here; it would have to be parenthesized. - - var switchExpressionCase = _syntaxFactory.SwitchExpressionArm( - pattern, - ParseWhenClause(Precedence.Coalescing), - // Help out in the case where a user is converting a switch statement to a switch expression. - // Consume the `:` as a `=>` and report an error. - this.CurrentToken.Kind == SyntaxKind.ColonToken - ? this.EatTokenAsKind(SyntaxKind.EqualsGreaterThanToken) - : this.EatToken(SyntaxKind.EqualsGreaterThanToken), - ParseExpressionCore()); - - // If we're not making progress, abort - if (switchExpressionCase.Width == 0 && this.CurrentToken.Kind != SyntaxKind.CommaToken) - break; - - arms.Add(switchExpressionCase); - if (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken) + var arms = _pool.AllocateSeparated(); + + while (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken) { - var commaToken = this.CurrentToken.Kind == SyntaxKind.SemicolonToken - ? this.EatTokenAsKind(SyntaxKind.CommaToken) - : this.EatToken(SyntaxKind.CommaToken); - arms.AddSeparator(commaToken); + // Help out in the case where a user is converting a switch statement to a switch expression. Note: + // `default(...)` and `default` will also be consumed as a legal syntactic patterns (though the + // latter will fail during binding). So if the user has `default:` we will recover fine as we + // handle the errant colon below. + var errantCase = this.CurrentToken.Kind == SyntaxKind.CaseKeyword + ? AddError(this.EatToken(), ErrorCode.ERR_BadCaseInSwitchArm) + : null; + + var savedState = _termState; + _termState |= TerminatorState.IsPatternInSwitchExpressionArm; + var pattern = ParsePattern(Precedence.Coalescing, whenIsKeyword: true); + _termState = savedState; + + // We use a precedence that excludes lambdas, assignments, and a conditional which could have a + // lambda on the right, because we need the parser to leave the EqualsGreaterThanToken to be + // consumed by the switch arm. The strange side-effect of that is that the conditional expression is + // not permitted as a constant expression here; it would have to be parenthesized. + + var switchExpressionCase = _syntaxFactory.SwitchExpressionArm( + pattern, + ParseWhenClause(Precedence.Coalescing), + // Help out in the case where a user is converting a switch statement to a switch expression. + // Consume the `:` as a `=>` and report an error. + this.CurrentToken.Kind == SyntaxKind.ColonToken + ? this.EatTokenAsKind(SyntaxKind.EqualsGreaterThanToken) + : this.EatToken(SyntaxKind.EqualsGreaterThanToken), + ParseExpressionCore()); + + // If we're not making progress, abort + if (errantCase is null && switchExpressionCase.FullWidth == 0 && this.CurrentToken.Kind != SyntaxKind.CommaToken) + break; + + if (errantCase != null) + switchExpressionCase = AddLeadingSkippedSyntax(switchExpressionCase, errantCase); + + arms.Add(switchExpressionCase); + if (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken) + { + var commaToken = this.CurrentToken.Kind == SyntaxKind.SemicolonToken + ? this.EatTokenAsKind(SyntaxKind.CommaToken) + : this.EatToken(SyntaxKind.CommaToken); + arms.AddSeparator(commaToken); + } } - } - return _pool.ToListAndFree(arms); + return _pool.ToListAndFree(arms); + } } private ListPatternSyntax ParseListPattern(bool whenIsKeyword) diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/ObjectDisplay.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/ObjectDisplay.cs index 087670e7f73ea..68aae1cb8193a 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/ObjectDisplay.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/ObjectDisplay.cs @@ -324,7 +324,7 @@ internal static string FormatLiteral(char c, ObjectDisplayOptions options) if (options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints)) { builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString()); - builder.Append(" "); + builder.Append(' '); } var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); diff --git a/src/Compilers/CSharp/Portable/Symbols/AbstractTypeParameterMap.cs b/src/Compilers/CSharp/Portable/Symbols/AbstractTypeParameterMap.cs index 02db5b18b20fe..aa296bc401c1d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AbstractTypeParameterMap.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AbstractTypeParameterMap.cs @@ -42,10 +42,10 @@ private string GetDebuggerDisplay() result.Append(this.GetType().Name); foreach (var kv in Mapping) { - result.Append(" ").Append(kv.Key).Append(":").Append(kv.Value.Type); + result.Append(' ').Append(kv.Key).Append(':').Append(kv.Value.Type); } - return result.Append("]").ToString(); + return result.Append(']').ToString(); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs index 9e0c07b2cc20f..5c3dce114585a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TemplateSymbol.cs @@ -203,7 +203,7 @@ private SynthesizedAttributeData TrySynthesizeDebuggerDisplayAttribute() sb.Append(fieldName); sb.Append(" = {"); sb.Append(fieldName); - sb.Append("}"); + sb.Append('}'); } if (this.Properties.Length > displayCount) diff --git a/src/Compilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs b/src/Compilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs index 92edbed9326d4..6c99ed0785ceb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Attributes/AttributeData.cs @@ -147,7 +147,7 @@ internal bool IsSecurityAttribute(CSharpCompilation compilation) StringBuilder stringBuilder = pooledStrbuilder.Builder; stringBuilder.Append(className); - stringBuilder.Append("("); + stringBuilder.Append('('); bool first = true; @@ -175,7 +175,7 @@ internal bool IsSecurityAttribute(CSharpCompilation compilation) first = false; } - stringBuilder.Append(")"); + stringBuilder.Append(')'); return pooledStrbuilder.ToStringAndFree(); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamespaceSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamespaceSymbol.cs index 9197399182076..1a0d3eb7abb3e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamespaceSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamespaceSymbol.cs @@ -91,6 +91,18 @@ private ImmutableArray GetMemberTypesPrivate() return StaticCast.From(_lazyFlattenedTypes); } + internal override NamespaceSymbol GetNestedNamespace(ReadOnlyMemory name) + { + EnsureAllMembersLoaded(); + + if (lazyNamespaces.TryGetValue(name, out var ns)) + { + return ns; + } + + return null; + } + public sealed override ImmutableArray GetMembers(ReadOnlyMemory name) { EnsureAllMembersLoaded(); diff --git a/src/Compilers/CSharp/Portable/Symbols/NamespaceSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamespaceSymbol.cs index 9999d50b2db2c..e64a8c90a12e3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamespaceSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamespaceSymbol.cs @@ -262,7 +262,7 @@ internal NamespaceSymbol LookupNestedNamespace(ImmutableArray GetNestedNamespace(name.AsMemory()); - internal NamespaceSymbol GetNestedNamespace(ReadOnlyMemory name) + internal virtual NamespaceSymbol GetNestedNamespace(ReadOnlyMemory name) { foreach (var sym in this.GetMembers(name)) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs index d546b5152b57b..b5608cedf39bb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs @@ -86,7 +86,7 @@ public static string GetMemberName(string name, TypeSymbol explicitInterfaceType } } - builder.Append("."); + builder.Append('.'); builder.Append(name); return pooled.ToStringAndFree(); diff --git a/src/Compilers/CSharp/Portable/Symbols/SymbolCompletionState.cs b/src/Compilers/CSharp/Portable/Symbols/SymbolCompletionState.cs index 6bfd061ef6933..4cc96f758aec6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/SymbolCompletionState.cs +++ b/src/Compilers/CSharp/Portable/Symbols/SymbolCompletionState.cs @@ -150,7 +150,7 @@ public override string ToString() any = true; } } - result.Append(")"); + result.Append(')'); return result.ToString(); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/RefKindVector.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/RefKindVector.cs index 81850458ef2e0..8920a3cf5a92a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/RefKindVector.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/RefKindVector.cs @@ -86,21 +86,21 @@ public string ToRefKindString() var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; - builder.Append("{"); + builder.Append('{'); int i = 0; foreach (var word in this.Words()) { if (i > 0) { - builder.Append(","); + builder.Append(','); } builder.AppendFormat("{0:x8}", word); i++; } - builder.Append("}"); + builder.Append('}'); Debug.Assert(i > 0); return pooledBuilder.ToStringAndFree(); diff --git a/src/Compilers/CSharp/Portable/Symbols/TypedConstantExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypedConstantExtensions.cs index a09291deac485..5b8ba5f5ca48a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypedConstantExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypedConstantExtensions.cs @@ -118,7 +118,7 @@ private static string DisplayUnsignedEnumConstant(TypedConstant constant, Specia } valueStringBuilder.Append(typeName); - valueStringBuilder.Append("."); + valueStringBuilder.Append('.'); valueStringBuilder.Append(field.Name); } } @@ -196,7 +196,7 @@ private static string DisplaySignedEnumConstant(TypedConstant constant, SpecialT } valueStringBuilder.Append(typeName); - valueStringBuilder.Append("."); + valueStringBuilder.Append('.'); valueStringBuilder.Append(field.Name); } } diff --git a/src/Compilers/CSharp/Portable/Syntax/GenericNameSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/GenericNameSyntax.cs index 67ed2f3a3f589..a34c78d972884 100644 --- a/src/Compilers/CSharp/Portable/Syntax/GenericNameSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/GenericNameSyntax.cs @@ -23,7 +23,7 @@ public bool IsUnboundGenericName internal override string ErrorDisplayName() { var pb = PooledStringBuilder.GetInstance(); - pb.Builder.Append(Identifier.ValueText).Append("<").Append(',', Arity - 1).Append(">"); + pb.Builder.Append(Identifier.ValueText).Append('<').Append(',', Arity - 1).Append('>'); return pb.ToStringAndFree(); } } diff --git a/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.FloatingValueSet.cs b/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.FloatingValueSet.cs index 3ec60d80bcb4e..4a7f7a4f7c850 100644 --- a/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.FloatingValueSet.cs +++ b/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.FloatingValueSet.cs @@ -163,7 +163,7 @@ public override string ToString() b.Append("NaN"); string more = this._numbers.ToString()!; if (b.Length > 1 && more.Length > 1) - b.Append(","); + b.Append(','); b.Append(more); return b.ToString(); } diff --git a/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NintValueSet.cs b/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NintValueSet.cs index 93484119d657e..34b5d01c8d42a 100644 --- a/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NintValueSet.cs +++ b/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NintValueSet.cs @@ -134,10 +134,10 @@ public override string ToString() if (_hasSmall) builder.Append("Small"); if (_hasSmall && !_values.IsEmpty) - builder.Append(","); + builder.Append(','); builder.Append(_values.ToString()); if (_hasLarge && builder.Length > 0) - builder.Append(","); + builder.Append(','); if (_hasLarge) builder.Append("Large"); return psb.ToStringAndFree(); diff --git a/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NuintValueSet.cs b/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NuintValueSet.cs index 24ed1814d555c..e3a2de81aa340 100644 --- a/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NuintValueSet.cs +++ b/src/Compilers/CSharp/Portable/Utilities/ValueSetFactory.NuintValueSet.cs @@ -116,7 +116,7 @@ public override string ToString() var builder = psb.Builder; builder.Append(_values.ToString()); if (_hasLarge && builder.Length > 0) - builder.Append(","); + builder.Append(','); if (_hasLarge) builder.Append("Large"); return psb.ToStringAndFree(); diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index ad0792c691d08..6e7d9b3e04cc1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - Argument {0} nelze předat s klíčovým slovem ref ve verzi jazyka {1}. Pokud chcete argumenty ref předat parametrům in, upgradujte na verzi jazyka {2} nebo vyšší. + Argument {0} nelze předat s klíčovým slovem ref v jazykové verzi {1}. Pokud chcete argumenty ref předat parametrům in, upgradujte na verzi jazyka {2} nebo vyšší. @@ -414,22 +414,22 @@ The CollectionBuilderAttribute builder type must be a non-generic class or struct. - Typ tvůrce CollectionBuilderAttribute musí být neobecná třída nebo struktura. + Typ sestavení CollectionBuilderAttribute musí být neobecná třída nebo struktura. Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - Nelze najít přístupnou metodu '{0}' s očekávaným podpisem: statická metoda s jedním parametrem typu ReadOnlySpan<{1}> a návratovým typem '{2}'. + Nepodařilo se najít přístupnou metodu {0} s očekávaným podpisem: statická metoda s jedním parametrem typu ReadOnlySpan<{1}> a návratovým typem {2}. '{0}' has a CollectionBuilderAttribute but no element type. - '{0}' má collectionBuilderAttribute, ale žádný typ elementu. + {0} má CollectionBuilderAttribute, ale žádný typ prvku. A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + Výraz kolekce typu {0} nelze v tomto kontextu použít, protože může být vystaven mimo aktuální obor. @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + Pro výraz kolekce neexistuje žádný cílový typ. @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + Typ {0} nelze inicializovat pomocí výrazu kolekce, protože typ není konstruovatelný. @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + Strom výrazů nesmí obsahovat výraz kolekce. @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + Funkce {0} není v jazyce C# 12.0 k dispozici. Použijte prosím jazykovou verzi {1} nebo vyšší. @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - Příkaz foreach ve vloženém poli typu '{0}' není podporován. + příkaz foreach u vloženého pole typu {0} není podporován @@ -954,7 +954,7 @@ Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer. - Pole vloženého elementu pole nelze deklarovat jako povinné, jen pro čtení, nestálé nebo jako vyrovnávací paměť pevné velikosti. + Pole vloženého prvku pole nelze deklarovat jako povinné, jen pro čtení, nestálé nebo jako vyrovnávací paměť s pevnou velikostí. @@ -969,7 +969,7 @@ Method '{0}' must be non-generic or have arity {1} to match '{2}'. - Metoda '{0}' musí být neobecná nebo musí mít aritu {1}, aby odpovídala '{2}'. + Metoda {0} musí být neobecná nebo musí mít aritu {1}, aby odpovídala {2}. @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + Metodu {0} nelze použít jako zachycovací modul, protože jeho nadřazený typ má parametry typu. @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + Argument diagnosticId atributu Experimental musí být platný identifikátor @@ -1684,7 +1684,7 @@ 'readonly' modifier must be specified after 'ref'. - Modifikátor readonly musí být zadaný za ref. + Modifikátor readonly musí být zadán za parametrem ref. @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + Spread operátor .. nejde použít pro proměnné typu {0}, protože {0} neobsahuje veřejnou definici instance nebo rozšíření pro {1}. @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + výrazy kolekce @@ -2294,7 +2294,7 @@ ref readonly parameters - ref readonly parameters + parametry ref readonly @@ -2434,22 +2434,22 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + Argument {0} by se měl předávat s klíčovým slovem in Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + Argument by se měl předávat s klíčovým slovem in Argument {0} should be passed with 'ref' or 'in' keyword - Argument {0} by se měl předat s klíčovým slovem ref nebo in. + Argument {0} by se měl předávat s klíčovým slovem ref nebo in Argument should be passed with 'ref' or 'in' keyword - Argument by měl být předán s klíčovým slovem ref nebo in. + Argument by se měl předávat s klíčovým slovem ref nebo in @@ -2464,22 +2464,22 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - Modifikátor ref pro argument {0} odpovídající parametru in je ekvivalentní k in. Zvažte možnost použít místo toho in. + Modifikátor ref pro argument {0} odpovídající parametru in je ekvivalentem in. Místo toho zvažte použití in. The 'ref' modifier for an argument corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - Modifikátor ref pro argument odpovídající parametru in je ekvivalentem in. Zvažte možnost použít místo toho in. + Modifikátor ref pro argument odpovídající parametru in je ekvivalentem in. Místo toho zvažte použití in. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + Je nutné zadat parametr atributu SizeConst. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + Je nutné zadat parametr atributu SizeConst. @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - U výrazu kolekce typu '{0}' může dojít k neočekávaným přidělením haldy. Zvažte explicitní vytvoření pole a následného převodu na '{0}', aby přidělení bylo explicitní. + U výrazu kolekce typu {0} může dojít k neočekávanému přidělení haldy. Zvažte explicitní vytvoření pole a následného převodu na {0}, aby bylo přidělení explicitní. Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - U výrazu kolekce může dojít k neočekávaným přidělením haldy. Zvažte explicitní vytvoření pole a následného převodu na konečný typ, aby bylo přidělení explicitní. + U výrazu kolekce může dojít k neočekávanému přidělení haldy. Zvažte explicitní vytvoření pole a následného převodu na konečný typ, aby bylo přidělení explicitní. Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - Výraz kolekce typu '{0}' může mít za následek neočekávané přidělení haldy z důvodu použití tečky (..). Zvažte explicitní vytvoření pole a následného převodu na '{0}', aby přidělení bylo explicitní. + Výraz kolekce typu {0} může z důvodu použití spread operátoru .. způsobovat neočekávaná přidělení haldy. Zvažte explicitní vytvoření pole a následného převodu na {0}, aby bylo přidělení explicitní. Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - Ve výrazu kolekce může dojít k neočekávaným přidělením haldy, protože se používá tečky (.).). Zvažte explicitní vytvoření pole a následného převodu na konečný typ, aby bylo přidělení explicitní. + Výraz kolekce může z důvodu použití spread operátoru .. způsobovat neočekávaná přidělení haldy. Zvažte explicitní vytvoření pole a následného převodu na konečný typ, aby bylo přidělení explicitní. @@ -2694,52 +2694,52 @@ Inline array conversion operator will not be used for conversion from expression of the declaring type. - Operátor převodu vloženého pole nebude použit pro převod z výrazu deklarujícího typu. + Operátor převodu vloženého pole se nepoužije pro převod z výrazu deklarujícího typu. Inline array conversion operator will not be used for conversion from expression of the declaring type. - Operátor převodu vloženého pole nebude použit pro převod z výrazu deklarujícího typu. + Operátor převodu vloženého pole se nepoužije pro převod z výrazu deklarujícího typu. Inline array indexer will not be used for element access expression. - Indexer vloženého pole nebude použit pro výraz přístupu k elementu. + Indexer vloženého pole se nepoužije pro výraz přístupu k prvku. Inline array indexer will not be used for element access expression. - Indexer vloženého pole nebude použit pro výraz přístupu k elementu. + Indexer vloženého pole se nepoužije pro výraz přístupu k prvku. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + Funkce jazyka Inline arrays není podporována pro typ vloženého pole, který není platný jako argument typu nebo má typ prvku, který není platný jako argument typu. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + Funkce jazyka Inline arrays není podporována pro typ vloženého pole, který není platný jako argument typu nebo má typ prvku, který není platný jako argument typu. Inline array 'Slice' method will not be used for element access expression. - Metoda Slice vloženého pole nebude použita pro výraz přístupu k elementu. + Metoda Slice vloženého pole se nepoužije pro výraz přístupu k prvku. Inline array 'Slice' method will not be used for element access expression. - Metoda Slice vloženého pole nebude použita pro výraz přístupu k elementu. + Metoda Slice vloženého pole se nepoužije pro výraz přístupu k prvku. Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - Modifikátor druhu odkazu parametru '{0}' neodpovídá odpovídajícímu parametru '{1}' ve skrytém členu. + Modifikátor druhu odkazu parametru {0} neodpovídá odpovídajícímu parametru {1} ve skrytém členu. Reference kind modifier of parameter doesn't match the corresponding parameter in hidden member. - Modifikátor druhu odkazu parametru neodpovídá odpovídajícímu parametru ve skrytém členovi. + Modifikátor druhu odkazu parametru neodpovídá odpovídajícímu parametru ve skrytém členu. @@ -2844,7 +2844,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - Modifikátor druhu odkazu parametru '{0}' neodpovídá odpovídajícímu parametru '{1}' v přepsaném nebo implementovaném členu. + Modifikátor druhu odkazu parametru {0} neodpovídá odpovídajícímu parametru {1} v přepsaném nebo implementovaném členu. @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - Primární parametr konstruktoru '{0}' je stínován členem ze základu. + Parametr primárního konstruktoru {0} je stínován členem z báze. Primary constructor parameter is shadowed by a member from base - Parametr primárního konstruktoru je stínován členem ze základní třídy. + Parametr primárního konstruktoru je stínován členem z báze @@ -2959,7 +2959,7 @@ Argument {0} should be a variable because it is passed to a 'ref readonly' parameter - Argument {0} by měla být proměnná, protože je předána parametru ref readonly. + Argumentem {0} by měla být proměnná, protože se předává parametru ref readonly @@ -2969,12 +2969,12 @@ A default value is specified for 'ref readonly' parameter '{0}', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - Pro parametr ref readonly '{0}' je zadána výchozí hodnota, ale parametr ref readonly by měl být použit pouze pro odkazy. Zvažte deklarování parametru jako in. + Pro parametr ref readonly {0} je zadaná výchozí hodnota, ale parametr ref readonly by se měl používat pouze pro odkazy. Zvažte deklarování parametru jako in. A default value is specified for 'ref readonly' parameter, but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - Pro parametr ref readonly je zadána výchozí hodnota, ale parametr ref readonly by měl být použit pouze pro odkazy. Zvažte deklarování parametru jako in. + Pro parametr ref readonly je zadaná výchozí hodnota, ale parametr ref readonly by se měl používat pouze pro odkazy. Zvažte deklarování parametru jako in. @@ -4860,7 +4860,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - Modifikátor druhu odkazu parametru '{0}' neodpovídá odpovídajícímu parametru '{1}' v cíli. + Modifikátor druhu odkazu parametru {0} neodpovídá odpovídajícímu parametru {1} v cíli. @@ -5135,12 +5135,12 @@ Ref field '{0}' should be ref-assigned before use. - '{0}' referenčního pole musí být před použitím přiřazen odkazem. + Před použitím by se mělo přiřadit referenční pole {0}. Ref field should be ref-assigned before use. - Před použitím by mělo být přiřazeno referenční pole. + Před použitím by se mělo přiřadit referenční pole. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index e528c41f08af0..ffeb3b5d2ce0d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - L’argument {0} ne peut pas être passé avec le mot clé 'ref' dans la version de langage {1}. Pour passer les arguments 'ref' aux paramètres 'in', effectuez une mise à niveau vers la version de langage {2} ou une version ultérieure. + L’argument {0} ne peut pas être passé avec le mot clé « ref » dans la version de langage {1}. Pour passer les arguments « ref » aux paramètres « in », effectuez une mise à niveau vers la version de langage {2} ou une version ultérieure. @@ -414,22 +414,22 @@ The CollectionBuilderAttribute builder type must be a non-generic class or struct. - Le type du générateur CollectionBuilderAttribute doit être une classe ou un struct non générique. + Le type de générateur CollectionBuilderAttribute doit être une classe ou un struct non générique. Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - Impossible de trouver une méthode '{0}' accessible avec la signature attendue : une méthode statique avec un seul paramètre de type 'ReadOnlySpan<{1}>' et le type de retour '{2}'. + Désolé... Nous n’avons pas pou trouver une méthode « {0} » accessible avec la signature attendue : une méthode statique avec un seul paramètre de type « ReadOnlySpan<{1}> » et le type de retour « {2} ». '{0}' has a CollectionBuilderAttribute but no element type. - '{0}' a un CollectionBuilderAttribute mais aucun type d’élément. + « {0} » a un CollectionBuilderAttribute mais aucun type d’élément. A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + Vous ne pouvez pas utiliser une expression de collection de type « {0} » dans ce contexte, car elle peut être exposée en dehors de l’étendue actuelle. @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + Il n’existe aucun type cible pour l’expression de collection. @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + Désolé... Nous ne pouvons pas initialiser le type « {0} » avec une expression de collection, car le type n’est pas constructible. @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + Une arborescence de l’expression ne peut pas contenir une expression de collection. @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + La fonctionnalité « {0} » n’est pas disponible en C# 12.0. Veuillez utiliser la version de langage {1} ou une version ultérieure. @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - l’instruction foreach sur un tableau inline de type '{0}' n’est pas prise en charge + l’instruction foreach sur un tableau inlined de type « {0} » n’est pas prise en charge @@ -954,7 +954,7 @@ Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer. - Le champ d’élément de tableau inline ne peut pas être déclaré comme obligatoire, en lecture seule, volatile ou en tant que mémoire tampon de taille fixe. + Le champ d’élément de tableau inlined ne peut pas être déclaré comme obligatoire, en lecture seule, volatile ou en tant que mémoire tampon de taille fixe. @@ -969,7 +969,7 @@ Method '{0}' must be non-generic or have arity {1} to match '{2}'. - La méthode '{0}' doit être non générique ou avoir des {1} d’arité pour correspondre à '{2}'. + La méthode « {0} » doit être non générique ou avoir une arité {1} pour correspondre à « {2} ». @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + La méthode « {0} » ne peut pas être utilisée comme intercepteur car elle ou son type contenant a des paramètres de type. @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + L’argument diagnosticId de l’attribut « Experimental » doit être un identificateur valide @@ -1684,7 +1684,7 @@ 'readonly' modifier must be specified after 'ref'. - Le modificateur 'readonly' doit être spécifié après 'ref'. + Vous devez spécifier le modificateur « readonly » après « ref ». @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + L’opérateur spread « .. » ne peut pas fonctionner sur des variables de type « {0} », car « {0} » ne contient pas de définition d’extension ou d’instance publique pour « {1} » @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + expressions de collection @@ -2434,22 +2434,22 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + L’argument {0} doit être passé avec le mot clé « in » Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + L’argument doit être passé avec le mot clé « in » Argument {0} should be passed with 'ref' or 'in' keyword - L’argument {0} doit être passé avec mot clé 'ref' ou 'in' + L’argument {0} doit être passé avec le mot clé « ref » ou « in » Argument should be passed with 'ref' or 'in' keyword - L’argument doit être passé avec 'ref' ou 'in' mot clé + L’argument doit être passé avec le mot clé « ref » ou « in » @@ -2464,22 +2464,22 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - Le modificateur 'ref' de l’argument {0} correspondant au paramètre 'in' est équivalent à 'in'. Utilisez 'in' à la place. + Le modificateur « ref » de l’argument {0} correspondant au paramètre « in » est équivalent à « in ». Envisagez d’utiliser « in » à la place. The 'ref' modifier for an argument corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - Le modificateur 'ref' d’un argument correspondant au paramètre 'in' équivaut à 'in'. Utilisez 'in' à la place. + Le modificateur « ref » d’un argument correspondant au paramètre « in » est équivalent à « in ». Envisagez d’utiliser « in » à la place. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + Vous devez spécifier un paramètre d’attribut « SizeConst ». Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + Vous devez spécifier un paramètre d’attribut « SizeConst ». @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - L’expression de collection de type '{0}' peut entraîner des allocations de tas inattendues. Créez explicitement un tableau, puis convertissez-le en '{0}' pour rendre l’allocation explicite. + L’expression de collection de type « {0} » peut entraîner des allocations de segment de mémoire inattendues. Envisagez de créer explicitement un tableau, puis convertissez-le en « {0} » pour rendre l’allocation explicite. Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - L’expression de collection peut entraîner des allocations de tas inattendues. Créez explicitement un tableau, puis convertissez vers le type final pour rendre l’allocation explicite. + L’expression de collection peut entraîner des allocations de segment de mémoire inattendues. Envisagez de créer explicitement un tableau, puis convertissez-le en type final pour rendre l’allocation explicite. Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - L’expression de collection de type '{0}' peut entraîner des allocations de segment de mémoire inattendues en raison de l’utilisation des spreads '..'. Créez explicitement un tableau, puis convertissez-le en '{0}' pour rendre l’allocation explicite. + L’expression de collection de type « {0} » peut entraîner des allocations de segment de mémoire inattendues en raison de l’utilisation de spreads « .. ». Envisagez de créer explicitement un tableau, puis convertissez-le en « {0} » pour rendre l’allocation explicite. Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - L’expression de collection peut entraîner des allocations de segment de mémoire inattendues en raison de l’utilisation des spreads '..'. Créez explicitement un tableau, puis convertissez vers le type final pour rendre l’allocation explicite. + L’expression de collection peut entraîner des allocations de segment de mémoire inattendues en raison d’une utilisation de spreads « .. ». Envisagez de créer explicitement un tableau, puis convertissez-le en type final pour rendre l’allocation explicite. @@ -2694,47 +2694,47 @@ Inline array conversion operator will not be used for conversion from expression of the declaring type. - L’opérateur de conversion de tableau inline ne sera pas utilisé pour la conversion à partir de l’expression du type déclarant. + L’opérateur de conversion de tableau inlined ne sera pas utilisé pour la conversion à partir de l’expression du type déclarant. Inline array conversion operator will not be used for conversion from expression of the declaring type. - L’opérateur de conversion de tableau inline ne sera pas utilisé pour la conversion à partir de l’expression du type déclarant. + L’opérateur de conversion de tableau inlined ne sera pas utilisé pour la conversion à partir de l’expression du type déclarant. Inline array indexer will not be used for element access expression. - L’indexeur de tableau inline ne sera pas utilisé pour l’expression d’accès à l’élément. + L’indexeur du tableau inlined ne sera pas utilisée pour l’expression d’accès à l’élément. Inline array indexer will not be used for element access expression. - L’indexeur de tableau inline ne sera pas utilisé pour l’expression d’accès à l’élément. + L’indexeur du tableau inlined ne sera pas utilisée pour l’expression d’accès à l’élément. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + La fonctionnalité de langage « inline arrays » n’est pas prise en charge pour un type de tableau inlined non valide en tant qu’argument de type ou dont le type d’élément n’est pas valide en tant qu’argument de type. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + La fonctionnalité de langage « inline arrays » n’est pas prise en charge pour un type de tableau inlined non valide en tant qu’argument de type ou dont le type d’élément n’est pas valide en tant qu’argument de type. Inline array 'Slice' method will not be used for element access expression. - La méthode 'Slice' du tableau inline ne sera pas utilisée pour l’expression d’accès à l’élément. + La méthode « Slice » du tableau inlined ne sera pas utilisée pour l’expression d’accès à l’élément. Inline array 'Slice' method will not be used for element access expression. - La méthode 'Slice' du tableau inline ne sera pas utilisée pour l’expression d’accès à l’élément. + La méthode « Slice » du tableau inlined ne sera pas utilisée pour l’expression d’accès à l’élément. Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - Le modificateur de genre de référence du paramètre '{0}' ne correspond pas au paramètre correspondant '{1}' dans le membre masqué. + Le modificateur de genre de référence du paramètre « {0} » ne correspond pas au paramètre « {1} » correspondant dans le membre masqué. @@ -2844,12 +2844,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - Le modificateur de genre de référence du paramètre '{0}' ne correspond pas au paramètre correspondant '{1}' dans le membre substitué ou implémenté. + Le modificateur de genre de référence du paramètre « {0} » ne correspond pas au paramètre « {1} » correspondant dans le membre implémenté ou remplacé. Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member. - Le modificateur de genre de référence du paramètre ne correspond pas au paramètre correspondant dans le membre substitué ou implémenté. + Le modificateur de genre de référence du paramètre ne correspond pas au paramètre correspondant dans le membre implémenté ou remplacé. @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - Le paramètre de constructeur principal '{0}' est ombré par un membre de la base. + Le paramètre de constructeur principal « {0} » est ombré par un membre de la base. Primary constructor parameter is shadowed by a member from base - Le paramètre du constructeur principal est ombré par un membre de la base + Le paramètre de constructeur principal est ombré par un membre de la base @@ -2959,22 +2959,22 @@ Argument {0} should be a variable because it is passed to a 'ref readonly' parameter - L’argument {0} doit être une variable, car il est passé à un paramètre 'ref readonly' + L’argument {0} doit être une variable, car il est passé à un paramètre « ref readonly » Argument should be a variable because it is passed to a 'ref readonly' parameter - L’argument doit être une variable, car il est passé à un paramètre 'ref readonly' + L’argument doit être une variable, car il est passé à un paramètre « ref readonly » A default value is specified for 'ref readonly' parameter '{0}', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - Une valeur par défaut est spécifiée pour le paramètre 'ref readonly' '{0}', mais 'ref readonly' doit être utilisé uniquement pour les références. Déclarez le paramètre comme 'in'. + Une valeur par défaut est spécifiée pour le paramètre « ref readonly » « {0} », mais « ref readonly » doit être utilisé uniquement pour les références. Envisagez de déclarer le paramètre comme « in ». A default value is specified for 'ref readonly' parameter, but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - Une valeur par défaut est spécifiée pour le paramètre 'ref readonly', mais 'ref readonly' doit être utilisé uniquement pour les références. Déclarez le paramètre comme 'in'. + Une valeur par défaut est spécifiée pour le paramètre « ref readonly », mais « ref readonly » doit être utilisé uniquement pour les références. Envisagez de déclarer le paramètre comme « in ». @@ -4860,7 +4860,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - Le modificateur de genre de référence du paramètre '{0}' ne correspond pas au paramètre correspondant '{1}' dans la cible. + Le modificateur de genre de référence du paramètre « {0} » ne correspond pas au paramètre « {1} » correspondant dans la cible. @@ -5135,12 +5135,12 @@ Ref field '{0}' should be ref-assigned before use. - Le champ ref '{0}' doit être assigné à la référence avant utilisation. + Le champ ref « {0} »doit être assigné à ref avant son utilisation. Ref field should be ref-assigned before use. - Le champ ref doit être assigné à la référence avant d’être utilisé. + Le champ ref doit être assigné à ref avant son utilisation. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 9966c20084d9e..a9b912d7b8f52 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - 言語バージョン {1} では、引数 {0} を 'ref' キーワード (keyword)と共に渡すことはできません。'ref' 引数を 'in' パラメーターに渡すには、{2} 以上の言語バージョンにアップグレードしてください。 + 言語バージョン {1} では、引数 {0} を 'ref' キーワードと共に渡すことはできません。'ref' 引数を 'in' パラメーターに渡すには、言語バージョン {2} 以上にアップグレードしてください。 @@ -419,17 +419,17 @@ Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - 必要なシグネチャを持つアクセス可能な '{0}' メソッドが見つかりませんでした:'ReadOnlySpan<{1}>' 型の単一パラメーターを持つ静的メソッドと戻り値の型 '{2}'。 + 必要なシグネチャを持つアクセス可能な '{0}' メソッドが見つかりませんでした: 'ReadOnlySpan<{1}>' 型の単一のパラメーターと戻り値の型 '{2}' を持つ静的メソッド。 '{0}' has a CollectionBuilderAttribute but no element type. - '{0}' に CollectionBuilderAttribute がありますが、要素型がありません。 + '{0}' は CollectionBuilderAttribute を持っていますが、要素型を持っていません。 A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + 型 '{0}' のコレクション式は、現在のスコープ外に公開される可能性があるため、このコンテキストでは使用できません。 @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + コレクション式のターゲット型がありません。 @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + 型が構築可能でないため、コレクション式で型 '{0}' を初期化できません。 @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + 式ツリーにコレクション式を含めることはできません。 @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + 機能 '{0}' は C# 12.0 では使用できません。{1} 以上の言語バージョンを使用してください。 @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - 型 '{0}' のインライン配列の foreach ステートメントはサポートされていません + 型 '{0}' のインライン配列に対する foreach ステートメントはサポートされていません @@ -954,7 +954,7 @@ Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer. - インライン配列要素フィールドは、必須、読み取り専用、揮発性、または固定サイズ バッファーとして宣言できません。 + インライン配列要素フィールドは、必須バッファー、読み取り専用バッファー、揮発性バッファー、または固定サイズ バッファーとして宣言できません。 @@ -969,7 +969,7 @@ Method '{0}' must be non-generic or have arity {1} to match '{2}'. - メソッド '{0}' は非ジェネリックであるか、'{2}' と一致するアリティ {1} を持っている必要があります。 + メソッド '{0}' は非ジェネリックであるか、'{2}' と一致するアリティ {1} を持つ必要があります。 @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + メソッド '{0}' は、含んでいる型に型パラメーターがあるため、インターセプターとして使用できません。 @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + 'Experimental' 属性への diagnosticId 引数は有効な識別子である必要があります @@ -1489,7 +1489,7 @@ A ref readonly parameter cannot have the Out attribute. - ref 読み取り専用パラメーターに Out 属性を指定することはできません。 + ref readonly パラメーターに Out 属性を指定することはできません。 @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + '{0}' が '{1}' のパブリック インスタンス定義または拡張機能定義を含んでいないため、スプレッド演算子 '..' は型 '{0}' の変数に対して使用できません。 @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + コレクション式 @@ -2294,7 +2294,7 @@ ref readonly parameters - ref 読み取り専用パラメーター + ref readonly パラメーター @@ -2434,22 +2434,22 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + 引数 {0} は 'in' キーワードと共に渡す必要があります Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + 引数は 'in' キーワードと共に渡す必要があります Argument {0} should be passed with 'ref' or 'in' keyword - 引数 {0} は 'ref' または 'in' キーワード (keyword)と共に渡す必要があります + 引数 {0} は 'ref' キーワードまたは 'in' キーワードと共に渡す必要があります Argument should be passed with 'ref' or 'in' keyword - 引数は 'ref' または 'in' キーワード (keyword)で渡す必要があります + 引数は 'ref' キーワードまたは 'in' キーワードと共に渡す必要があります @@ -2464,7 +2464,7 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - 'in' パラメーターに対応する引数 {0} の 'ref' 修飾子が 'in' と同じです。代わりに 'in' を使用することを検討してください。 + 'in' パラメーターに対応する引数 {0} の 'ref' 修飾子は 'in' と同じです。代わりに 'in' を使用することを検討してください。 @@ -2474,12 +2474,12 @@ Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + 属性パラメーター 'SizeConst' を指定する必要があります。 Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + 属性パラメーター 'SizeConst' を指定する必要があります。 @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - '{0}' 型のコレクション式では、予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、'{0}' に変換して割り当てを明示的にすることを検討してください。 + 型 '{0}' のコレクション式では、予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、'{0}' に変換して割り当てを明示的に行うことを検討してください。 Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - コレクション式で予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、最後の型に変換して割り当てを明示的にすることを検討してください。 + コレクション式では、予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、最終的な型に変換して割り当てを明示的に行うことを検討してください。 Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - 型 '{0}' のコレクション式では、'..' 拡散が使用されているため、予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、'{0}' に変換して割り当てを明示的にすることを検討してください。 + 型 '{0}' のコレクション式では、'..' スプレッドの使用により、予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、'{0}' に変換して割り当てを明示的に行うことを検討してください。 Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - '..' 拡散が使用されているため、コレクション式で予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、最後の型に変換して割り当てを明示的にすることを検討してください。 + コレクション式では、'..' スプレッドの使用により、予期しないヒープ割り当てが発生する可能性があります。配列を明示的に作成してから、最終的な型に変換して割り当てを明示的に行うことを検討してください。 @@ -2694,12 +2694,12 @@ Inline array conversion operator will not be used for conversion from expression of the declaring type. - インライン配列変換演算子は、宣言する型の式からの変換には使用されません。 + インライン配列変換演算子は、宣言型の式からの変換には使用されません。 Inline array conversion operator will not be used for conversion from expression of the declaring type. - インライン配列変換演算子は、宣言する型の式からの変換には使用されません。 + インライン配列変換演算子は、宣言型の式からの変換には使用されません。 @@ -2714,12 +2714,12 @@ 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + 「インライン配列」言語機能は、型引数として無効なインライン配列型、または型引数として無効な要素型を持つインライン配列型ではサポートされていません。 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + 「インライン配列」言語機能は、型引数として無効なインライン配列型、または型引数として無効な要素型を持つインライン配列型ではサポートされていません。 @@ -2734,12 +2734,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - パラメーター '{0}' の参照の種類修飾子が、非表示のメンバーの対応するパラメーター '{1}' と一致しません。 + パラメーター '{0}' の参照種類修飾子が、非表示メンバーの対応するパラメーター '{1}' と一致しません。 Reference kind modifier of parameter doesn't match the corresponding parameter in hidden member. - パラメーターの参照の種類の修飾子が、非表示のメンバーの対応するパラメーターと一致しません。 + パラメーターの参照種類修飾子が、非表示メンバーの対応するパラメーターと一致しません。 @@ -2844,12 +2844,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - パラメーター '{0}' の参照の種類修飾子が、オーバーライドされたメンバーまたは実装されるメンバーの対応するパラメーター '{1}' と一致しません。 + パラメーター '{0}' の参照種類修飾子が、オーバーライドされたメンバーまたは実装されたメンバーの対応するパラメーター '{1}' と一致しません。 Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member. - パラメーターの参照の種類修飾子が、オーバーライドされたメンバーまたは実装されたメンバーの対応するパラメーターと一致しません。 + パラメーターの参照種類修飾子が、オーバーライドされたメンバーまたは実装されたメンバーの対応するパラメーターと一致しません。 @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - プライマリ コンストラクター パラメーター '{0}' は、ベースのメンバーによってシャドウされています。 + プライマリ コンストラクター パラメーター '{0}' は基底のメンバーによってシャドウされます。 Primary constructor parameter is shadowed by a member from base - プライマリ コンストラクター パラメーターがベースのメンバーによってシャドウされています + プライマリ コンストラクター パラメーターは基底のメンバーによってシャドウされます。 @@ -2969,12 +2969,12 @@ A default value is specified for 'ref readonly' parameter '{0}', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - 'ref readonly' パラメーター '{0}' に既定値が指定されていますが、'ref readonly' は参照にのみ使用する必要があります。パラメーターを 'in' として宣言することを検討してください。 + 'ref readonly' パラメーター '{0}' に既定値が指定されていますが、'ref readonly' は参照のみに使用してください。パラメーターを 'in' として宣言することを検討してください。 A default value is specified for 'ref readonly' parameter, but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - 'ref readonly' パラメーターに既定値が指定されていますが、'ref readonly' は参照にのみ使用する必要があります。パラメーターを 'in' として宣言することを検討してください。 + 'ref readonly' パラメーターには既定値が指定されていますが、'ref readonly' は参照のみに使用してください。パラメーターを 'in' として宣言することを検討してください。 @@ -4860,12 +4860,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - パラメーター '{0}' の参照の種類修飾子が、ターゲット内の対応するパラメーター '{1}' と一致しません。 + パラメーター '{0}' の参照種類修飾子が、ターゲット内の対応するパラメーター '{1}' と一致しません。 Reference kind modifier of parameter doesn't match the corresponding parameter in target. - パラメーターの参照の種類修飾子が、ターゲット内の対応するパラメーターと一致しません。 + パラメーターの参照種類修飾子が、ターゲット内の対応するパラメーターと一致しません。 @@ -5135,12 +5135,12 @@ Ref field '{0}' should be ref-assigned before use. - 参照フィールド '{0}' は、使用する前に参照を割り当てる必要があります。 + ref フィールド '{0}' は、使用する前に参照を割り当てる必要があります。 Ref field should be ref-assigned before use. - 参照フィールドは、使用する前に参照を割り当てる必要があります。 + ref フィールドは、使用する前に参照を割り当てる必要があります。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index ca79d48758eec..af81279285d1a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - Nie można przekazać {0} argumentu za pomocą słowa kluczowego "ref" w wersji językowej {1}. Aby przekazać argumenty "ref" do parametrów "in", uaktualnij do wersji językowej {2} lub nowszej. + Argument {0} nie może być przekazywany ze słowem kluczowym „ref” w wersji językowej {1}. Aby przekazać argumenty „ref” do parametrów „in”, uaktualnij do wersji językowej {2} lub nowszej. @@ -414,22 +414,22 @@ The CollectionBuilderAttribute builder type must be a non-generic class or struct. - Typ konstruktora CollectionBuilderAttribute musi być klasą lub strukturą nie ogólną. + Typ konstruktora CollectionBuilderAttribute musi być klasą lub strukturą nie generycznej. Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - Nie można odnaleźć dostępnej metody '{0}' z oczekiwaną sygnaturą: metoda statyczna z pojedynczym parametrem typu "ReadOnlySpan<{1}>" i zwracanym typem '{2}'. + Nie można odnaleźć dostępnej metody „{0}” z oczekiwanym podpisem: metoda statyczna z pojedynczym parametrem typu „ReadOnlySpan<{1}>” i zwracanym typem „{2}”. '{0}' has a CollectionBuilderAttribute but no element type. - '{0}' ma atrybut CollectionBuilderAttribute, ale nie ma typu elementu. + Element „{0}” ma atrybut CollectionBuilderAttribute, ale nie ma typu elementu. A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + Nie można użyć wyrażenia kolekcji typu „{0}” w tym kontekście, ponieważ może ono być uwidocznione poza bieżącym zakresem. @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + Brak typu docelowego dla wyrażenia kolekcji. @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + Nie można zainicjować typu „{0}” z wyrażeniem kolekcji, ponieważ nie można go skonstruować. @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + Drzewo wyrażenia nie może zawierać wyrażenia kolekcji. @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + Funkcja „{0}” nie jest dostępna w języku C# 12.0. Użyj języka w wersji {1} lub nowszej. @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - instrukcja foreach w tablicy wbudowanej typu '{0}' nie jest obsługiwana + instrukcja foreach w tablicy wbudowanej typu „{0}” nie jest obsługiwana @@ -954,7 +954,7 @@ Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer. - Pole elementu tablicy wbudowanej nie może być deklarowane jako wymagane, tylko do odczytu, nietrwałe ani jako bufor o stałym rozmiarze. + Pole elementu tablicy wbudowanej nie może być zadeklarowane jako wymagane, tylko do odczytu, nietrwałe ani jako bufor o stałym rozmiarze. @@ -969,7 +969,7 @@ Method '{0}' must be non-generic or have arity {1} to match '{2}'. - '{0}' metody nie może być rodzajowa lub musi mieć {1} liczby argumentów, aby była zgodna z '{2}'. + Metoda „{0}” musi być niegeneryczna lub mieć liczbę argumentów{1}, aby pasować do „{2}”. @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + Metoda „{0}” nie może być używana jako metoda interceptora, ponieważ jej typ zawierający ma parametry typu. @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + Argument diagnosticId atrybutu „Experimental” musi być prawidłowym identyfikatorem @@ -1489,7 +1489,7 @@ A ref readonly parameter cannot have the Out attribute. - Parametr ref tylko do odczytu nie może mieć atrybutu Out. + Parametr ref readonly nie może mieć atrybutu Out. @@ -1684,7 +1684,7 @@ 'readonly' modifier must be specified after 'ref'. - Modyfikator "readonly" musi być określony po instrukcji "ref". + Modyfikator „readonly” musi być określony po znaku „ref”. @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + Operator rozłożenia „..” nie może operować na zmiennych typu „{0}”, ponieważ „{0}” nie zawiera publicznego wystąpienia lub definicji rozszerzenia dla elementu „{1}” @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + wyrażenia kolekcji @@ -2294,7 +2294,7 @@ ref readonly parameters - ref readonly parameters + parametry tylko do odczytu ref @@ -2394,7 +2394,7 @@ string escape character - znak ucieczki ciągu + ciąg — znak ucieczki @@ -2434,22 +2434,22 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + Argument {0} powinien być przekazywany za pomocą słowa kluczowego „in” Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + Argument powinien być przekazywany za pomocą słowa kluczowego „in” Argument {0} should be passed with 'ref' or 'in' keyword - Argument {0} powinien zostać przekazany ze słowem kluczowym "ref" lub "in" + Argument {0} powinien być przekazywany za pomocą słowa kluczowego „ref” lub „in” Argument should be passed with 'ref' or 'in' keyword - Argument powinien zostać przekazany ze słowem kluczowym "ref" lub "in" + Argument powinien być przekazywany za pomocą słowa kluczowego „ref” lub „in” @@ -2464,22 +2464,22 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - Modyfikator "ref" dla argumentu {0} odpowiadający parametrowi "in" jest równoważny wartości "in". Zamiast tego rozważ użycie elementu "in". + Modyfikator „ref” dla argumentu {0} odpowiadającego parametrowi „in” jest równoważny parametrowi „in”. Zamiast tego rozważ użycie parametru „in”. The 'ref' modifier for an argument corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - Modyfikator "ref" dla argumentu odpowiadającego parametrowi "in" jest równoważny wartości "in". Zamiast tego rozważ użycie elementu "in". + Modyfikator „ref” dla argumentu odpowiadającego parametrowi „in” jest równoważny parametrowi „in”. Zamiast tego rozważ użycie parametru „in”. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + Należy określić parametr atrybutu „SizeConst”. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + Należy określić parametr atrybutu „SizeConst”. @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - Wyrażenie kolekcji typu '{0}' może spowodować nieoczekiwane alokacje sterty. Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na '{0}', aby alokacja była jawna. + Wyrażenie kolekcji typu „{0}” może spowodować nieoczekiwane alokacje sterty. Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na „{0}”, aby jawnie utworzyć alokację. Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - Wyrażenie kolekcji może spowodować nieoczekiwane alokacje sterty. Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na typ końcowy, aby alokacja była jawna. + Wyrażenie kolekcji może spowodować nieoczekiwane alokacje sterty. Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na typ końcowy, aby jawnie utworzyć alokację. Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - Wyrażenie kolekcji typu '{0}' może spowodować nieoczekiwane alokacje sterty z powodu użycia spreadów ".". Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na '{0}', aby alokacja była jawna. + Wyrażenie kolekcji typu „{0}” może spowodować nieoczekiwane alokacje sterty z powodu użycia „.”. Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na „{0}”, aby jawnie utworzyć alokację. Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - Wyrażenie kolekcji może powodować nieoczekiwane alokacje sterty z powodu użycia spreadów ".". Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na typ końcowy, aby alokacja była jawna. + Wyrażenie kolekcji może spowodować nieoczekiwane alokacje sterty z powodu użycia spreadów „.”. Rozważ jawne utworzenie tablicy, a następnie przekonwertowanie na typ końcowy, aby jawnie utworzyć alokację. @@ -2704,42 +2704,42 @@ Inline array indexer will not be used for element access expression. - Indeksator tablicy wbudowanej nie będzie używany na potrzeby wyrażenia dostępu do elementu. + Indeksator tablicy wbudowanej nie będzie używany na potrzeby wyrażenia dostępu do elementów. Inline array indexer will not be used for element access expression. - Indeksator tablicy wbudowanej nie będzie używany na potrzeby wyrażenia dostępu do elementu. + Indeksator tablicy wbudowanej nie będzie używany na potrzeby wyrażenia dostępu do elementów. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + Funkcja języka „Tablice wbudowane” nie jest obsługiwana w przypadku typu tablicy wbudowanej, który jest nieprawidłowy jako argument typu lub ma typ elementu, który jest nieprawidłowy jako argument typu. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + Funkcja języka „Tablice wbudowane” nie jest obsługiwana w przypadku typu tablicy wbudowanej, który jest nieprawidłowy jako argument typu lub ma typ elementu, który jest nieprawidłowy jako argument typu. Inline array 'Slice' method will not be used for element access expression. - Metoda "Slice" tablicy wbudowanej nie będzie używana na potrzeby wyrażenia dostępu do elementu. + Metoda „Slice” tablicy wbudowanej nie będzie używana dla wyrażenia dostępu do elementu. Inline array 'Slice' method will not be used for element access expression. - Metoda "Slice" tablicy wbudowanej nie będzie używana na potrzeby wyrażenia dostępu do elementu. + Metoda „Slice” tablicy wbudowanej nie będzie używana dla wyrażenia dostępu do elementu. Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - Modyfikator rodzaju odwołania '{0}' parametru nie jest zgodny z odpowiednim '{1}' parametru w ukrytej składowej. + Modyfikator rodzaju odwołania parametru „{0}” nie pasuje do odpowiadającego mu parametru „{1}” w ukrytej składowej. Reference kind modifier of parameter doesn't match the corresponding parameter in hidden member. - Modyfikator rodzaju odwołania parametru nie jest zgodny z odpowiadającym mu parametrem w ukrytej składowej. + Modyfikator rodzaju odwołania parametru nie pasuje do odpowiedniego parametru w ukrytym elemencie członkowskim. @@ -2844,12 +2844,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - Modyfikator rodzaju odwołania '{0}' parametru nie jest zgodny z odpowiadającym mu parametrem '{1}' w przesłoniętym lub zaimplementowanym elemencie członkowskim. + Modyfikator rodzaju odwołania parametru „{0}” nie jest zgodny z odpowiednim parametrem „{1}” w przesłoniętej lub zaimplementowanej składowej. Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member. - Modyfikator rodzaju odwołania parametru nie jest zgodny z odpowiadającym mu parametrem w przesłoniętym lub zaimplementowanym elemencie członkowskim. + Modyfikator rodzaju odwołania parametru nie jest zgodny z odpowiednim parametrem w przesłoniętej lub zaimplementowanej składowej. @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - Podstawowy parametr konstruktora '{0}' jest zacieniowany przez składową z bazy. + Podstawowy parametr konstruktora „{0}” jest w tle przez składową z bazy. Primary constructor parameter is shadowed by a member from base - Podstawowy parametr konstruktora jest zacieniowany przez składową z bazy + Podstawowy parametr konstruktora jest zasłaniany przez składową z bazy @@ -2959,22 +2959,22 @@ Argument {0} should be a variable because it is passed to a 'ref readonly' parameter - Argument {0} powinien być zmienną, ponieważ jest przekazywany do parametru "ref readonly" + Argument {0} powinien być zmienną, ponieważ jest przekazywany do parametru „ref readonly” Argument should be a variable because it is passed to a 'ref readonly' parameter - Argument powinien być zmienną, ponieważ jest przekazywany do parametru "ref readonly" + Argument powinien być zmienną, ponieważ jest przekazywany do parametru „ref readonly” A default value is specified for 'ref readonly' parameter '{0}', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - Dla parametru "ref readonly" '{0}' określono wartość domyślną, ale element "ref readonly" powinien być używany tylko dla odwołań. Rozważ zadeklarowanie parametru jako "in". + Dla parametru „ref readonly” „{0}” określono wartość domyślną, ale parametr „ref readonly” powinien być używany tylko dla odwołań. Rozważ zadeklarowanie parametru jako „in”. A default value is specified for 'ref readonly' parameter, but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - Dla parametru "ref readonly" określono wartość domyślną, ale element "ref readonly" powinien być używany tylko dla odwołań. Rozważ zadeklarowanie parametru jako "in". + Dla parametru „ref readonly” określono wartość domyślną, ale parametr „ref readonly” powinien być używany tylko dla odwołań. Rozważ zadeklarowanie parametru jako „in”. @@ -4860,7 +4860,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - Modyfikator rodzaju odwołania '{0}' parametru nie jest zgodny z odpowiadającym mu parametrem '{1}' w lokalizacji docelowej. + Modyfikator rodzaju odwołania parametru „{0}” nie jest zgodny z odpowiadającym mu parametrem „{1}” w lokalizacji docelowej. @@ -5135,12 +5135,12 @@ Ref field '{0}' should be ref-assigned before use. - '{0}' pola odwołania należy przypisać przed użyciem. + Pole odwołania „{0}” powinno zostać przypisane do odwołania przed użyciem. Ref field should be ref-assigned before use. - Pole odwołania powinno zostać przypisane ponownie przed użyciem. + Pole odwołania należy przypisać do odwołania przed użyciem. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 8d9807a539041..833b2b6985380 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - O {0} argumento não pode ser passado com o palavra-chave 'ref' na versão da {1}. Para passar argumentos 'ref' para parâmetros 'in', atualize para a versão de {2} ou superior. + O argumento {0} não pode ser passado com o palavra-chave 'ref' na versão {1} da linguagem. Para passar argumentos 'ref' para parâmetros 'in', atualize para a versão {2} ou superior da linguagem. @@ -414,12 +414,12 @@ The CollectionBuilderAttribute builder type must be a non-generic class or struct. - O tipo de construtor CollectionBuilderAttribute deve ser uma classe ou struct não genérico. + O tipo de construtor CollectionBuilderAttribute deve ser uma classe ou estrutura não genérica. Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - Não foi possível localizar um método '{0}' acessível com a assinatura esperada: um método estático com um único parâmetro do tipo 'ReadOnlySpan<{1}>' e tipo de retorno '{2}'. + Não foi possível encontrar um método '{0}' acessível com a assinatura esperada: um método estático com um único parâmetro do tipo 'ReadOnlySpan<{1}>' e tipo de retorno '{2}'. @@ -429,7 +429,7 @@ A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + Uma expressão de coleção do tipo '{0}' não pode ser usada nesse contexto porque ela pode ser exposta fora do escopo atual. @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + Não há um tipo de destino para a expressão de coleção. @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + Não é possível inicializar o tipo '{0}' com uma expressão de coleção porque o tipo não é construível. @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + Uma árvore de expressão não pode conter uma expressão de coleção. @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + O recurso '{0}' não está disponível em C# 12.0. Use a versão da linguagem {1} ou superior. @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - não há suporte para a instrução foreach em uma matriz embutida '{0}' tipo + a instrução foreach em uma matriz em linha do tipo '{0}' não é compatível @@ -954,7 +954,7 @@ Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer. - O campo de elemento de matriz embutido não pode ser declarado como necessário, somente leitura, volátil ou como buffer de tamanho fixo. + O campo de elemento da matriz em linha não pode ser declarado como obrigatório, somente leitura, volátil ou como um buffer de tamanho fixo. @@ -969,7 +969,7 @@ Method '{0}' must be non-generic or have arity {1} to match '{2}'. - O '{0}' método deve ser não genérico ou ter arity {1} para corresponder '{2}'. + O método '{0}' deve ser não genérico ou ter aridade {1} para corresponder '{2}'. @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + O método '{0}' não pode ser usado como interceptor porque o tipo que o contém tem parâmetros de tipo. @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + O argumento diagnosticId para o atributo 'Experimental' deve ser um identificador válido @@ -1489,7 +1489,7 @@ A ref readonly parameter cannot have the Out attribute. - Um parâmetro readonly ref não pode ter o atributo Out. + Um parâmetro ref readonly não pode ter o atributo Out. @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + O operador de propagação '..' não pode operar em variáveis do tipo '{0}' porque '{0}' não contém uma instância pública ou definição de extensão para '{1}' @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + expressões de coleção @@ -2294,7 +2294,7 @@ ref readonly parameters - parâmetros somente leitura ref + parâmetros ref readonly @@ -2394,7 +2394,7 @@ string escape character - caractere de escape de cadeia de caracteres + cadeia de caracteres de escape @@ -2434,22 +2434,22 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + O argumento {0} deve ser passado com a palavra-chave 'in' Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + O argumento deve ser passado com a palavra-chave 'in' Argument {0} should be passed with 'ref' or 'in' keyword - O {0} argumento deve ser passado com 'ref' ou 'in' palavra-chave + O argumento {0} deve ser passado com a palavra-chave 'ref' ou 'in' Argument should be passed with 'ref' or 'in' keyword - O argumento deve ser passado com 'ref' ou 'in' palavra-chave + O argumento deve ser passado com a palavra-chave 'ref' ou 'in' @@ -2464,22 +2464,22 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - O modificador 'ref' do argumento {0} correspondente ao parâmetro 'in' é equivalente a 'in'. Considere usar 'in'. + O modificador 'ref' do argumento {0} correspondente ao parâmetro 'in' é equivalente a 'in'. Considere usar 'in' em vez disso. The 'ref' modifier for an argument corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - O modificador 'ref' de um argumento correspondente ao parâmetro 'in' é equivalente a 'in'. Considere usar 'in'. + O modificador 'ref' do argumento correspondente ao parâmetro 'in' é equivalente a 'in'. Considere usar 'in' em vez disso. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + O parâmetro de atribuição 'SizeConst' deve ser especificado. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + O parâmetro de atribuição 'SizeConst' deve ser especificado. @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - A expressão de coleção do tipo '{0}' pode incurar alocações de heap inesperadas. Considere criar explicitamente uma matriz e converter em '{0}' tornar a alocação explícita. + A expressão de coleção do tipo '{0}' pode incorrer em alocações inesperadas de heap. Considere a possibilidade de criar explicitamente uma matriz e, em seguida, converter para '{0}' para tornar a alocação explícita. Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - A expressão de coleção pode incursão de alocações de heap inesperadas. Considere criar explicitamente uma matriz e converter para o tipo final para tornar a alocação explícita. + A expressão Collection pode incorrer em alocações inesperadas de heap. Considere a possibilidade de criar explicitamente uma matriz e, em seguida, converter para o tipo final para tornar a alocação explícita. Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - A expressão de coleção do tipo '{0}' pode incursar alocações de heap inesperadas devido ao uso de espalhamentos '..'. Considere criar explicitamente uma matriz e converter em '{0}' tornar a alocação explícita. + A expressão de coleção do tipo '{0}' pode incorrer em alocações de heap inesperadas devido ao uso de spreads '..'. Considere a possibilidade de criar explicitamente uma matriz e, em seguida, converter para '{0}' para tornar a alocação explícita. Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - A expressão de coleção pode incursão de alocações de heap inesperadas devido ao uso de espalhamentos '..'. Considere criar explicitamente uma matriz e converter para o tipo final para tornar a alocação explícita. + A expressão Collection pode incorrer em alocações inesperadas de heap devido ao uso de spreads '..'. Considere a possibilidade de criar explicitamente uma matriz e, em seguida, converter para o tipo final para tornar a alocação explícita. @@ -2694,47 +2694,47 @@ Inline array conversion operator will not be used for conversion from expression of the declaring type. - O operador de conversão de matriz embutida não será usado para conversão da expressão do tipo declarante. + O operador de conversão de matriz em linha não será usado para a conversão da expressão do tipo declarativo. Inline array conversion operator will not be used for conversion from expression of the declaring type. - O operador de conversão de matriz embutida não será usado para conversão da expressão do tipo declarante. + O operador de conversão de matriz em linha não será usado para a conversão da expressão do tipo declarativo. Inline array indexer will not be used for element access expression. - O indexador de matriz embutido não será usado para a expressão de acesso a elementos. + O indexador de matriz em linha não será usado para a expressão de acesso ao elemento. Inline array indexer will not be used for element access expression. - O indexador de matriz embutido não será usado para a expressão de acesso a elementos. + O indexador de matriz em linha não será usado para a expressão de acesso ao elemento. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + O recurso de linguagem 'Inline arrays' não é compatível com um tipo de matriz em linha que não seja válido como argumento de tipo ou que tenha um tipo de elemento que não seja válido como argumento de tipo. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + O recurso de linguagem 'Inline arrays' não é compatível com um tipo de matriz em linha que não seja válido como argumento de tipo ou que tenha um tipo de elemento que não seja válido como argumento de tipo. Inline array 'Slice' method will not be used for element access expression. - O método 'Slice' da matriz embutida não será usado para a expressão de acesso ao elemento. + O método 'Slice' da matriz em linha não será usado para a expressão de acesso ao elemento. Inline array 'Slice' method will not be used for element access expression. - O método 'Slice' da matriz embutida não será usado para a expressão de acesso ao elemento. + O método 'Slice' da matriz em linha não será usado para a expressão de acesso ao elemento. Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - O modificador de tipo de referência '{0}' parâmetro não corresponde ao parâmetro correspondente '{1}' no membro oculto. + O modificador de tipo de referência do parâmetro '{0}' não corresponde ao parâmetro '{1}' correspondente no membro oculto. @@ -2844,7 +2844,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - O modificador de tipo de referência '{0}' parâmetro não corresponde ao parâmetro correspondente '{1}' no membro substituído ou implementado. + O modificador de tipo de referência do parâmetro '{0}' não corresponde ao parâmetro '{1}' correspondente no membro substituído ou implementado. @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - O parâmetro do '{0}' primário é sombreado por um membro da base. + O parâmetro '{0}' do construtor primário é sombreado por um membro da base. Primary constructor parameter is shadowed by a member from base - O parâmetro do construtor primário é sombreado por um membro da base + O parâmetro do construtor primário é sombreado por um membro da base. @@ -2959,7 +2959,7 @@ Argument {0} should be a variable because it is passed to a 'ref readonly' parameter - O {0} deve ser uma variável porque é passado para um parâmetro 'ref readonly' + O argumento {0} deve ser uma variável porque é passado para um parâmetro 'ref readonly' @@ -4860,7 +4860,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - O modificador de tipo de referência '{0}' parâmetro não corresponde ao parâmetro correspondente '{1}' no destino. + O modificador de tipo de referência do parâmetro '{0}' não corresponde ao parâmetro '{1}' correspondente no destino. @@ -5135,7 +5135,7 @@ Ref field '{0}' should be ref-assigned before use. - O campo '{0}' referência deve ser atribuído ref antes do uso. + O campo ref '{0}' deve ser atribuído como referência antes do uso. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 83563b75a7e72..2867a1693e6ca 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - Bağımsız {0}, dil sürümü sürümündeki 'ref' anahtar sözcüğüyle {1}. 'ref' bağımsız değişkenlerini 'in' parametrelerine geçiremiyorsanız, dil sürümüne {2} veya daha yüksek bir sürüme yükseltin. + {0} bağımsız değişkeni, {1} dil sürümündeki 'ref' anahtar sözcüğüyle geçirilemez. 'ref' bağımsız değişkenlerini 'in' parametrelerine geçirmek için{2} dil sürümüne yükseltin. @@ -419,17 +419,17 @@ Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - Beklenen imzaya sahip erişilebilir '{0}' yöntem bulunamadı: 'ReadOnlySpan<{1}>' türünde tek parametreli statik bir yöntem ve '{2}'. + Beklenen imzaya sahip erişilebilir bir '{0}' yöntemi bulunamadı: 'ReadOnlySpan<{1}>' türünde tek bir parametreye ve '{2}' dönüş türüne sahip statik bir yöntem. '{0}' has a CollectionBuilderAttribute but no element type. - '{0}' CollectionBuilderAttribute içeriyor ancak öğe türü yok. + '{0}' bir CollectionBuilderAttribute içeriyor ancak öğe türü yok. A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + '{0}' türündeki bir koleksiyon ifadesi, mevcut kapsamın dışında kullanıma sunulabileceğinden bu bağlamda kullanılamaz. @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + Koleksiyon ifadesi için hedef tür yok. @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + Tür, yapılandırılamadığından '{0}' türü bir koleksiyon ifadesiyle başlatılamıyor. @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + İfade ağacı bir koleksiyon ifadesi içermeyebilir. @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + '{0}' özelliği C# 12.0'da kullanılamıyor. Lütfen {1} veya daha yüksek dil sürümü kullanın. @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - türdeki satır içi dizideki foreach '{0}' desteklenmiyor + '{0}' türündeki satır içi dizideki foreach deyimi desteklenmiyor @@ -969,7 +969,7 @@ Method '{0}' must be non-generic or have arity {1} to match '{2}'. - Yöntem '{0}' genel olmamalı veya parametreyle eşleşmesi {1} parametre sayısı '{2}'. + '{0}' yöntemi, '{2}' ile eşleşmek için genel olmamalı veya {1} parametresine sahip olmalıdır. @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + '{0}' metodu, kapsayan türünde tür parametreleri olduğundan engelleyici olarak kullanılamaz. @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + 'Experimental' özniteliğinin diagnosticId bağımsız değişkeni geçerli bir tanımlayıcı olmalıdır @@ -1489,7 +1489,7 @@ A ref readonly parameter cannot have the Out attribute. - Bir ref salt okunur parametresi Out özniteliğine sahip olamaz. + Bir ref readonly parametresinin Out özniteliği olamaz. @@ -1684,7 +1684,7 @@ 'readonly' modifier must be specified after 'ref'. - 'readonly' değiştiricisi 'ref' öğesinden sonra belirtilmelidir. + 'readonly' değiştiricisi, 'ref' ardından belirtilmelidir. @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + '{0}', '{0}' için bir genel örnek veya uzantı tanımı içermediğinden '..' yayılma işleci, '{1}' türündeki değişkenler üzerinde çalışamaz @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + koleksiyon ifadeleri @@ -2294,7 +2294,7 @@ ref readonly parameters - salt okunur ref parametreleri + ref salt okunur parametreleri @@ -2434,17 +2434,17 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + {0} bağımsız değişkeni, 'in' anahtar sözcüğüyle geçirilmelidir Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + Bağımsız değişken, 'in' anahtar sözcüğüyle geçirilmelidir Argument {0} should be passed with 'ref' or 'in' keyword - Bağımsız {0} 'ref' veya 'in' anahtar sözcüğüyle geçirilmelidir + {0} bağımsız değişkeni 'ref' veya 'in' anahtar sözcüğüyle geçirilmelidir @@ -2464,22 +2464,22 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - 'in' parametresine karşılık gelen bağımsız {0} 'ref' değiştiricisi 'in' ile eşdeğerdir. Bunun yerine 'in' kullanmayı düşünün. + 'in' parametresine karşılık gelen{0} bağımsız değişkeni için 'ref' değiştiricisi 'in' ile eşdeğerdir. Bunun yerine 'in' kullanmayı düşünün. The 'ref' modifier for an argument corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - 'in' parametresine karşılık gelen bir bağımsız değişkenin 'ref' değiştiricisi 'in' ile eşdeğerdir. Bunun yerine 'in' kullanmayı düşünün. + 'in' parametresine karşılık gelen bir bağımsız değişken için 'ref' değiştiricisi 'in' ile eşdeğerdir. Bunun yerine 'in' kullanmayı düşünün. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + 'SizeConst' öznitelik parametresi belirtilmelidir. Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + 'SizeConst' öznitelik parametresi belirtilmelidir. @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - Koleksiyon türündeki koleksiyon '{0}' beklenmeyen yığın ayırmaları olabilir. Açıkça bir dizi oluşturmayı, sonra ayırmayı açıkça '{0}' diziye dönüştürmeyi düşünün. + '{0}' türündeki koleksiyon ifadesi, beklenmeyen yığın ayırmalarına neden olabilir. Ayırmayı açık hale getirmek için açıkça bir dizi oluşturup sonra '{0}' olarak dönüştürmeyi düşünün. Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - Koleksiyon ifadesi beklenmeyen yığın ayırmaları içeriyor olabilir. Açıkça bir dizi oluşturmayı, sonra ayırmayı açık yapmak için son türe dönüştürmeyi düşünün. + Koleksiyon ifadesi, beklenmeyen yığın ayırmalarına neden olabilir. Ayırmayı açık hale getirmek için açıkça bir dizi oluşturup sonra son türe dönüştürmeyi düşünün. Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - '..' yayılmaları '{0}' türdeki koleksiyon ifadesi beklenmeyen yığın ayırmaları içerebilir. Açıkça bir dizi oluşturmayı, sonra ayırmayı açıkça '{0}' diziye dönüştürmeyi düşünün. + '{0}' türündeki koleksiyon ifadesi, '..' yayılmaları kullanılması nedeniyle beklenmeyen yığın ayırmalarına neden olabilir. Ayırmayı açık hale getirmek için açıkça bir dizi oluşturup sonra '{0}' olarak dönüştürmeyi düşünün. Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - Koleksiyon ifadesi , '..' yayılmaları kullanımı nedeniyle beklenmeyen yığın ayırmaları içeriyor olabilir. Açıkça bir dizi oluşturmayı, sonra ayırmayı açık yapmak için son türe dönüştürmeyi düşünün. + Koleksiyon ifadesi, '..' yayılmaları kullanılması nedeniyle beklenmeyen yığın ayırmalarına neden olabilir. Ayırmayı açık hale getirmek için açıkça bir dizi oluşturup sonra son türe dönüştürmeyi düşünün. @@ -2694,47 +2694,47 @@ Inline array conversion operator will not be used for conversion from expression of the declaring type. - Satır içi dizi dönüştürme işleci, bildirim türünün ifadelerinden dönüştürme için kullanılmaz. + Bildirim türündeki ifadeden dönüştürme için satır içi dizi dönüştürme işleci kullanılmaz. Inline array conversion operator will not be used for conversion from expression of the declaring type. - Satır içi dizi dönüştürme işleci, bildirim türünün ifadelerinden dönüştürme için kullanılmaz. + Bildirim türündeki ifadeden dönüştürme için satır içi dizi dönüştürme işleci kullanılmaz. Inline array indexer will not be used for element access expression. - Satır içi dizi dizin oluşturucusu öğe erişim ifadesi için kullanılmaz. + Satır içi dizi dizin oluşturucu, öğe erişim ifadesi için kullanılmaz. Inline array indexer will not be used for element access expression. - Satır içi dizi dizin oluşturucusu öğe erişim ifadesi için kullanılmaz. + Satır içi dizi dizin oluşturucu, öğe erişim ifadesi için kullanılmaz. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + 'Satır içi diziler' dil özelliği, tür bağımsız değişkeni olarak geçerli olmayan veya tür bağımsız değişkeni olarak geçerli olmayan öğe türüne sahip satır içi dizi türü için desteklenmiyor. 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + 'Satır içi diziler' dil özelliği, tür bağımsız değişkeni olarak geçerli olmayan veya tür bağımsız değişkeni olarak geçerli olmayan öğe türüne sahip satır içi dizi türü için desteklenmiyor. Inline array 'Slice' method will not be used for element access expression. - Satır içi dizi 'Slice' yöntemi öğe erişim ifadesi için kullanılmaz. + Satır içi dizi 'Slice' yöntemi, öğe erişimi ifadesi için kullanılmaz. Inline array 'Slice' method will not be used for element access expression. - Satır içi dizi 'Slice' yöntemi öğe erişim ifadesi için kullanılmaz. + Satır içi dizi 'Slice' yöntemi, öğe erişimi ifadesi için kullanılmaz. Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - Parametre türü değiştiricisi '{0}', gizli üyedeki karşılık gelen parametre '{1}' eşleşmiyor. + '{0}' parametresinin başvuru türü değiştiricisi, gizli üyedeki karşılık gelen '{1}' parametresiyle eşleşmiyor. @@ -2844,12 +2844,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - Parametre türü değiştiricisi'{0}' geçersiz kılınan veya uygulanan üyedeki '{1}' parametre türü değiştiricisi ile eşleşmiyor. + '{0}' parametresinin başvuru türü değiştiricisi, geçersiz kılınan veya uygulanan üyedeki karşılık gelen '{1}' parametresiyle eşleşmiyor. Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member. - Parametrenin başvuru türü değiştiricisi geçersiz kılınan veya uygulanan üyedeki karşılık gelen parametreyle eşleşmiyor. + Parametrenin başvuru türü değiştiricisi, geçersiz kılınan veya uygulanan üyedeki karşılık gelen parametreyle eşleşmiyor. @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - Birincil oluşturucu parametresi '{0}' temeldeki bir üye tarafından gölgelendi. + '{0}' birincil oluşturucu parametresi, temel üye tarafından gölgelendi. Primary constructor parameter is shadowed by a member from base - Birincil oluşturucu parametresi temeldeki bir üye tarafından gölgelendi + Birincil oluşturucu parametresi, temel üye tarafından gölgelendi. @@ -2959,7 +2959,7 @@ Argument {0} should be a variable because it is passed to a 'ref readonly' parameter - Bağımsız {0} bir 'ref readonly' parametresine geçirildiğinden değişken olmalıdır + {0} bağımsız değişkeni bir 'ref readonly' parametresine geçirildiğinden bir değişken olmalıdır @@ -2969,12 +2969,12 @@ A default value is specified for 'ref readonly' parameter '{0}', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - 'ref readonly' parametresi için varsayılan bir değer '{0}' ancak 'ref readonly' yalnızca başvurular için kullanılmalıdır. Parametreyi 'in' olarak bildirmeyi düşünün. + '{0}' 'ref readonly' parametresi için varsayılan değer belirtildi ancak 'ref readonly' yalnızca başvurular için kullanılmalıdır. Parametreyi 'in' olarak bildirmeyi düşünün. A default value is specified for 'ref readonly' parameter, but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - 'ref readonly' parametresi için varsayılan bir değer belirtildi, ancak 'ref readonly' yalnızca başvurular için kullanılmalıdır. Parametreyi 'in' olarak bildirmeyi düşünün. + 'ref readonly' parametresi için varsayılan değer belirtildi ancak 'ref readonly' yalnızca başvurular için kullanılmalıdır. Parametreyi 'in' olarak bildirmeyi düşünün. @@ -4860,7 +4860,7 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - Parametre türü değiştiricisi '{0}', hedefte karşılık gelen parametre '{1}' eşleşmiyor. + {0} parametresinin başvuru türü değiştiricisi, hedefte karşılık gelen{1} parametresiyle eşleşmiyor. @@ -5135,12 +5135,12 @@ Ref field '{0}' should be ref-assigned before use. - Başvuru alanı '{0}' önce başvuru atanmalı. + '{0}' başvuru alanı, kullanımdan önce başvurarak atanmalıdır. Ref field should be ref-assigned before use. - Başvuru alanı, kullanımdan önce başvuruya atanabilir olmalıdır. + Başvuru alanı, kullanımdan önce başvurarak atanmalıdır. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 65ae87c3995e9..8d577454c57f5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -184,7 +184,7 @@ Argument {0} may not be passed with the 'ref' keyword in language version {1}. To pass 'ref' arguments to 'in' parameters, upgrade to language version {2} or greater. - 無法使用語言版本 {1} 中的 'ref' 關鍵字傳遞引數 {0}。若要將 'ref' 引數傳遞至 'in' 參數,請升級為語言版本 {2} 或更新版本。 + 引數 {0} 可能無法以語言版本 {1} 中的 'ref' 關鍵字傳遞。若要將 'ref' 引數傳遞至 'in' 參數,請升級為語言版本 {2} 或更新版本。 @@ -414,12 +414,12 @@ The CollectionBuilderAttribute builder type must be a non-generic class or struct. - CollectionBuilderAttribute 產生器類型必須是非泛型類別或結構。 + CollectionBuilderAttribute 組建器類型必須是非泛型類別或結構。 Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. - Could not find an accessible '{0}' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan<{1}>' and return type '{2}'. + 找不到具有預期簽章的可存取 '{0}' 方法:具有類型 'ReadOnlySpan<{1}>' 的單一參數,且傳回類型 '{2}' 的靜態方法。 @@ -429,7 +429,7 @@ A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. - A collection expression of type '{0}' cannot be used in this context because it may be exposed outside of the current scope. + 無法在此內容中使用類型 '{0}' 的集合運算式,因為它可能會在目前範圍外公開。 @@ -449,7 +449,7 @@ There is no target type for the collection expression. - There is no target type for the collection expression. + 集合運算式沒有目標類型。 @@ -459,7 +459,7 @@ Cannot initialize type '{0}' with a collection expression because the type is not constructible. - Cannot initialize type '{0}' with a collection expression because the type is not constructible. + 無法使用集合運算式將類型 '{0}' 初始化,因為該類型為不可建構。 @@ -649,7 +649,7 @@ An expression tree may not contain a collection expression. - An expression tree may not contain a collection expression. + 運算式樹狀架構不得包含集合運算式。 @@ -724,7 +724,7 @@ Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. - Feature '{0}' is not available in C# 12.0. Please use language version {1} or greater. + C# 12.0. 中無法使用 '{0}' 功能。請使用語言版本 {1} 或更高的版本。 @@ -944,7 +944,7 @@ foreach statement on an inline array of type '{0}' is not supported - 不支援在類型為 '{0}' 的內嵌陣列上 foreach 語句 + 不支援類型為 '{0}' 之內嵌陣列上的 foreach 陳述式 @@ -954,7 +954,7 @@ Inline array element field cannot be declared as required, readonly, volatile, or as a fixed size buffer. - 內嵌陣列元素欄位不能宣告為必要、唯讀、揮發性或固定大小緩衝區。 + 不可將內嵌陣列元素欄位宣告為必要、readonly、易變或為固定的大小緩衝區。 @@ -994,7 +994,7 @@ Method '{0}' cannot be used as an interceptor because its containing type has type parameters. - Method '{0}' cannot be used as an interceptor because its containing type has type parameters. + 方法 '{0}' 無法作為攔截器,因為其包含類型具有類型參數。 @@ -1139,7 +1139,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + 'Experimental' 屬性的 diagnosticId 引數必須是有效的識別碼 @@ -1489,7 +1489,7 @@ A ref readonly parameter cannot have the Out attribute. - ref 唯讀參數不能有 Out 屬性。 + ref readonly 參數不能有 Out 屬性。 @@ -1684,7 +1684,7 @@ 'readonly' modifier must be specified after 'ref'. - 'ref' 後面必須指定 'readonly' 修飾詞。 + 'readonly' 修飾元必須在 'ref' 之後指定。 @@ -1899,7 +1899,7 @@ Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' - Spread operator '..' cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}' + 擴展運算子 '..' 無法在類型 '{0}' 的變數上運作,因為 '{0}' 不包含 '{1}' 的公用執行個體或延伸模組定義 @@ -2164,7 +2164,7 @@ collection expressions - collection expressions + 集合運算式 @@ -2294,7 +2294,7 @@ ref readonly parameters - ref 唯讀參數 + ref readonly 參數 @@ -2434,22 +2434,22 @@ Argument {0} should be passed with the 'in' keyword - Argument {0} should be passed with the 'in' keyword + 引數 {0} 應該以 'in' 的關鍵字傳遞 Argument should be passed with the 'in' keyword - Argument should be passed with the 'in' keyword + 引數應該以 'in' 的關鍵字傳遞 Argument {0} should be passed with 'ref' or 'in' keyword - 引數 {0} 應以 'ref' 或 'in' 關鍵字傳遞 + 引數 {0} 應該以 'ref' 或 'in' 的關鍵字傳遞 Argument should be passed with 'ref' or 'in' keyword - 引數應該以 'ref' 或 'in' 關鍵字傳遞 + 引數應該以 'ref' 或 'in' 的關鍵字傳遞 @@ -2464,22 +2464,22 @@ The 'ref' modifier for argument {0} corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - 對應至 'in' 參數之引數 {0} 的 'ref' 修飾詞相當於 'in'。請考慮改用 'in'。 + 對應至 'in' 參數之引數 {0} 的 'ref' 修飾元相當於 'in'。請考慮改為使用 'in'。 The 'ref' modifier for an argument corresponding to 'in' parameter is equivalent to 'in'. Consider using 'in' instead. - 對應至 'in' 參數之引數的 'ref' 修飾詞相當於 'in'。請考慮改用 'in'。 + 對應至 'in' 參數之引數的 'ref' 修飾元相當於 'in'。請考慮改為使用 'in'。 Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + 必須指定屬性參數 'SizeConst'。 Attribute parameter 'SizeConst' must be specified. - Attribute parameter 'SizeConst' must be specified. + 必須指定屬性參數 'SizeConst'。 @@ -2574,22 +2574,22 @@ Collection expression of type '{0}' may incur unexpected heap allocations. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - 類型為 '{0}' 的集合運算式可能會產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為 '{0}' 以明確配置。 + 類型 '{0}' 的集合運算式可能會產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為 '{0}' 以使配置明確化。 Collection expression may incur unexpected heap allocations. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - 集合運算式可能會產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為最終類型,使配置明確。 + 集合運算式可能會產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為最後類型以使配置明確化。 Collection expression of type '{0}' may incur unexpected heap allocations due to the use of '..' spreads. Consider explicitly creating an array, then converting to '{0}' to make the allocation explicit. - 類型 '{0}' 的集合運算式可能會因為使用 '..' 擴張而產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為 '{0}' 以明確配置。 + 類型 '{0}' 的集合運算式可能會因使用了 '..' 擴張而產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為 '{0}' 以使配置明確化。 Collection expression may incur unexpected heap allocations due to use of '..' spreads. Consider explicitly creating an array, then converting to the final type to make the allocation explicit. - 集合運算式可能會因為使用 '..' 擴張而產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為最終類型,使配置明確。 + 集合運算式可能會因使用了 '..' 擴張而產生未預期的堆積配置。請考慮明確地建立陣列,然後轉換為最後類型以使配置明確化。 @@ -2694,52 +2694,52 @@ Inline array conversion operator will not be used for conversion from expression of the declaring type. - 內嵌陣列轉換運算子將不會用於從宣告類型的運算式進行轉換。 + 內嵌陣列轉換運算子不會用於從宣告類型的運算式進行轉換。 Inline array conversion operator will not be used for conversion from expression of the declaring type. - 內嵌陣列轉換運算子將不會用於從宣告類型的運算式進行轉換。 + 內嵌陣列轉換運算子不會用於從宣告類型的運算式進行轉換。 Inline array indexer will not be used for element access expression. - 內嵌陣列索引子將不會用於元素存取運算式。 + 內嵌陣列索引子不會用於元素存取運算式。 Inline array indexer will not be used for element access expression. - 內嵌陣列索引子將不會用於元素存取運算式。 + 內嵌陣列索引子不會用於元素存取運算式。 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + 作為無效類型參數或具有作為無效類型參數之元素類型的内嵌陣列類型,都不支援「内嵌陣列」語言功能。 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. - 'Inline arrays' language feature is not supported for an inline array type that is not valid as a type argument, or has element type that is not valid as a type argument. + 作為無效類型參數或具有作為無效類型參數之元素類型的内嵌陣列類型,都不支援「内嵌陣列」語言功能。 Inline array 'Slice' method will not be used for element access expression. - 內嵌陣列 'Slice' 方法將不會用於元素存取運算式。 + 內嵌陣列 'Slice' 方法不會用於元素存取運算式。 Inline array 'Slice' method will not be used for element access expression. - 內嵌陣列 'Slice' 方法將不會用於元素存取運算式。 + 內嵌陣列 'Slice' 方法不會用於元素存取運算式。 Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in hidden member. - 參數的參照種類修飾詞 '{0}' 不符合隱藏成員中對應的參數 '{1}'。 + 參數 '{0}' 的參考種類修飾元不符合隱藏成員中的對應參數 '{1}'。 Reference kind modifier of parameter doesn't match the corresponding parameter in hidden member. - 參數的參考種類修飾詞不符合隱藏成員中對應的參數。 + 參數的參考種類修飾元不符合隱藏成員中的對應參數。 @@ -2844,12 +2844,12 @@ Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in overridden or implemented member. - 參數的參考種類修飾詞 '{0}' 不符合覆寫或實作成員中 '{1}' 對應的參數。 + 參數 '{0}' 的參考種類修飾元不符合已覆寫或已實作成員中的對應參數 '{1}'。 Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member. - 參數的參考種類修飾詞不符合覆寫或實作成員中對應的參數。 + 參數的參考種類修飾元不符合已覆寫或已實作成員中的對應參數。 @@ -2884,12 +2884,12 @@ Primary constructor parameter '{0}' is shadowed by a member from base. - 主要建構函式參數 '{0}' 由來自基底的成員陰影化。 + 主要建構函式參數 '{0}' 會伴隨著來自基底的成員。 Primary constructor parameter is shadowed by a member from base - 主要建構函式參數由來自基底的成員陰影 + 主要建構函式參數會伴隨著來自基底的成員 @@ -2959,22 +2959,22 @@ Argument {0} should be a variable because it is passed to a 'ref readonly' parameter - 引數 {0} 應為變數,因為它已傳遞至 'ref readonly' 參數 + 引數 {0} 應為變數,因為它會傳遞至 'ref readonly' 參數 Argument should be a variable because it is passed to a 'ref readonly' parameter - 引數應為變數,因為它傳遞至 'ref readonly' 參數 + 引數應為變數,因為它會傳遞至 'ref readonly' 參數 A default value is specified for 'ref readonly' parameter '{0}', but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - 已為 'ref readonly' 參數指定預設值 '{0}',但 'ref readonly' 只能用於參考。請考慮將參數宣告為 'in'。 + 已為 'ref readonly' 參數指定預設值 '{0}',但 'ref readonly' 應只用於參考。請考慮將參數宣告為 'in'。 A default value is specified for 'ref readonly' parameter, but 'ref readonly' should be used only for references. Consider declaring the parameter as 'in'. - 已為 'ref readonly' 參數指定預設值,但 'ref readonly' 只能用於參考。請考慮將參數宣告為 'in'。 + 已為 'ref readonly' 參數指定預設值,但 'ref readonly' 應只用於參考。請考慮將參數宣告為 'in'。 @@ -4860,12 +4860,12 @@ strument:TestCoverage 產生檢測要收集 Reference kind modifier of parameter '{0}' doesn't match the corresponding parameter '{1}' in target. - 參數的參考種類修飾詞 '{0}' 不符合目標中的對應參數 '{1}'。 + 參數 '{0}' 的參考種類修飾元不符合目標中的對應參數 '{1}'。 Reference kind modifier of parameter doesn't match the corresponding parameter in target. - 參數的參考種類修飾詞不符合目標中的對應參數。 + 參數的參考種類修飾元不符合目標中的對應參數。 @@ -5135,7 +5135,7 @@ strument:TestCoverage 產生檢測要收集 Ref field '{0}' should be ref-assigned before use. - ref 欄位 '{0}' 應在使用前以 ref 指派。 + Ref 欄位 '{0}' 應在使用前重新指派。 diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs index d25b343adfaac..03ec7e35918cc 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDynamicTests.cs @@ -8817,11 +8817,9 @@ .maxstack 1 "); } - /// - /// ref/out can be omitted at call-site. - /// [Fact] - public void InvokeMember_CallSiteRefOutOmitted() + [WorkItem("https://github.com/dotnet/roslyn/issues/71399")] + public void InvokeMember_CallSiteRefOutOmitted_01() { string source = @" public class C @@ -8840,6 +8838,8 @@ public void M() dynamic ld; f(d, d, ref lo, out ld); + + f(ref d, out d, ref lo, out ld); } public void f(ref long a, out int b, ref dynamic c, out object d) @@ -8848,17 +8848,60 @@ public void f(ref long a, out int b, ref dynamic c, out object d) d = null; } }"; + CreateCompilation(source).VerifyDiagnostics( + // (17,11): error CS1620: Argument 1 must be passed with the 'ref' keyword + // f(d, d, ref lo, out ld); + Diagnostic(ErrorCode.ERR_BadArgRef, "d").WithArguments("1", "ref").WithLocation(17, 11), + // (17,14): error CS1620: Argument 2 must be passed with the 'out' keyword + // f(d, d, ref lo, out ld); + Diagnostic(ErrorCode.ERR_BadArgRef, "d").WithArguments("2", "out").WithLocation(17, 14), + // (19,15): error CS1503: Argument 1: cannot convert from 'ref dynamic' to 'ref int' + // f(ref d, out d, ref lo, out ld); + Diagnostic(ErrorCode.ERR_BadArgType, "d").WithArguments("1", "ref dynamic", "ref int").WithLocation(19, 15), + // (19,22): error CS1503: Argument 2: cannot convert from 'out dynamic' to 'out int' + // f(ref d, out d, ref lo, out ld); + Diagnostic(ErrorCode.ERR_BadArgType, "d").WithArguments("2", "out dynamic", "out int").WithLocation(19, 22) + ); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71399")] + public void InvokeMember_CallSiteRefOutOmitted_02() + { + string source = @" +using System.Runtime.InteropServices; + +[ComImport, Guid(""0002095E-0000-0000-C000-000000000046"")] +public abstract class C1 +{ + public abstract void f(ref int a, out dynamic b, ref dynamic c, out object d); + public abstract void f(ref bool a, out dynamic b, ref dynamic c, out object d); +} + +public class C +{ + dynamic d = true; + + public void M(C1 c1) + { + object lo = null; + dynamic ld; + + c1.f(d, out d, ref lo, out ld); + } +} +"; CompileAndVerifyIL(source, "C.M", @" { - // Code size 141 (0x8d) + // Code size 142 (0x8e) .maxstack 9 .locals init (object V_0, //lo object V_1) //ld IL_0000: ldnull IL_0001: stloc.0 - IL_0002: ldsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009000}> C.<>o__2.<>p__0"" - IL_0007: brtrue.s IL_0067 - IL_0009: ldc.i4 0x102 + IL_0002: ldsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009200}> C.<>o__1.<>p__0"" + IL_0007: brtrue.s IL_0068 + IL_0009: ldc.i4 0x100 IL_000e: ldstr ""f"" IL_0013: ldnull IL_0014: ldtoken ""C"" @@ -8879,39 +8922,103 @@ .locals init (object V_0, //lo IL_0037: stelem.ref IL_0038: dup IL_0039: ldc.i4.2 - IL_003a: ldc.i4.0 - IL_003b: ldnull - IL_003c: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" - IL_0041: stelem.ref - IL_0042: dup - IL_0043: ldc.i4.3 - IL_0044: ldc.i4.s 9 - IL_0046: ldnull - IL_0047: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" - IL_004c: stelem.ref - IL_004d: dup - IL_004e: ldc.i4.4 - IL_004f: ldc.i4.s 17 - IL_0051: ldnull - IL_0052: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" - IL_0057: stelem.ref - IL_0058: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, System.Collections.Generic.IEnumerable, System.Type, System.Collections.Generic.IEnumerable)"" - IL_005d: call ""System.Runtime.CompilerServices.CallSite<<>A{00009000}> System.Runtime.CompilerServices.CallSite<<>A{00009000}>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" - IL_0062: stsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009000}> C.<>o__2.<>p__0"" - IL_0067: ldsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009000}> C.<>o__2.<>p__0"" - IL_006c: ldfld ""<>A{00009000} System.Runtime.CompilerServices.CallSite<<>A{00009000}>.Target"" - IL_0071: ldsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009000}> C.<>o__2.<>p__0"" - IL_0076: ldarg.0 - IL_0077: ldarg.0 - IL_0078: ldfld ""dynamic C.d"" - IL_007d: ldarg.0 - IL_007e: ldfld ""dynamic C.d"" - IL_0083: ldloca.s V_0 - IL_0085: ldloca.s V_1 - IL_0087: callvirt ""void <>A{00009000}.Invoke(System.Runtime.CompilerServices.CallSite, C, object, object, ref object, ref object)"" - IL_008c: ret + IL_003a: ldc.i4.s 17 + IL_003c: ldnull + IL_003d: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" + IL_0042: stelem.ref + IL_0043: dup + IL_0044: ldc.i4.3 + IL_0045: ldc.i4.s 9 + IL_0047: ldnull + IL_0048: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" + IL_004d: stelem.ref + IL_004e: dup + IL_004f: ldc.i4.4 + IL_0050: ldc.i4.s 17 + IL_0052: ldnull + IL_0053: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)"" + IL_0058: stelem.ref + IL_0059: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, string, System.Collections.Generic.IEnumerable, System.Type, System.Collections.Generic.IEnumerable)"" + IL_005e: call ""System.Runtime.CompilerServices.CallSite<<>A{00009200}> System.Runtime.CompilerServices.CallSite<<>A{00009200}>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0063: stsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009200}> C.<>o__1.<>p__0"" + IL_0068: ldsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009200}> C.<>o__1.<>p__0"" + IL_006d: ldfld ""<>A{00009200} System.Runtime.CompilerServices.CallSite<<>A{00009200}>.Target"" + IL_0072: ldsfld ""System.Runtime.CompilerServices.CallSite<<>A{00009200}> C.<>o__1.<>p__0"" + IL_0077: ldarg.1 + IL_0078: ldarg.0 + IL_0079: ldfld ""dynamic C.d"" + IL_007e: ldarg.0 + IL_007f: ldflda ""dynamic C.d"" + IL_0084: ldloca.s V_0 + IL_0086: ldloca.s V_1 + IL_0088: callvirt ""void <>A{00009200}.Invoke(System.Runtime.CompilerServices.CallSite, C1, object, ref object, ref object, ref object)"" + IL_008d: ret +} +").VerifyDiagnostics(); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71399")] + public void InvokeMember_CallSiteRefOutOmitted_03() + { + string source = @" +using System.Runtime.InteropServices; + +[ComImport, Guid(""0002095E-0000-0000-C000-000000000046"")] +public abstract class C1 +{ + public abstract void f(ref bool a, out dynamic b, ref dynamic c, out object d); } -"); + +public class C +{ + dynamic d = true; + + public void M(C1 c1) + { + object lo = null; + dynamic ld; + + c1.f(d, out d, ref lo, out ld); + } +} +"; + CompileAndVerifyIL(source, "C.M", @" +{ + // Code size 91 (0x5b) + .maxstack 5 + .locals init (object V_0, //lo + object V_1, //ld + bool V_2) + IL_0000: ldnull + IL_0001: stloc.0 + IL_0002: ldarg.1 + IL_0003: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__1.<>p__0"" + IL_0008: brtrue.s IL_002e + IL_000a: ldc.i4.0 + IL_000b: ldtoken ""bool"" + IL_0010: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_0015: ldtoken ""C"" + IL_001a: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_001f: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Type, System.Type)"" + IL_0024: call ""System.Runtime.CompilerServices.CallSite> System.Runtime.CompilerServices.CallSite>.Create(System.Runtime.CompilerServices.CallSiteBinder)"" + IL_0029: stsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__1.<>p__0"" + IL_002e: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__1.<>p__0"" + IL_0033: ldfld ""System.Func System.Runtime.CompilerServices.CallSite>.Target"" + IL_0038: ldsfld ""System.Runtime.CompilerServices.CallSite> C.<>o__1.<>p__0"" + IL_003d: ldarg.0 + IL_003e: ldfld ""dynamic C.d"" + IL_0043: callvirt ""bool System.Func.Invoke(System.Runtime.CompilerServices.CallSite, object)"" + IL_0048: stloc.2 + IL_0049: ldloca.s V_2 + IL_004b: ldarg.0 + IL_004c: ldflda ""dynamic C.d"" + IL_0051: ldloca.s V_0 + IL_0053: ldloca.s V_1 + IL_0055: callvirt ""void C1.f(ref bool, out dynamic, ref dynamic, out object)"" + IL_005a: ret +} +").VerifyDiagnostics(); } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs index d464a0a976566..c244c36502c73 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenOperators.cs @@ -5456,7 +5456,7 @@ private static string BuildSequenceOfBinaryExpressions_03(int count = 8192) { builder.Append("a["); builder.Append(i); - builder.Append("]"); + builder.Append(']'); builder.Append(" & "); builder.Append("f["); builder.Append(i); @@ -5465,7 +5465,7 @@ private static string BuildSequenceOfBinaryExpressions_03(int count = 8192) builder.Append("a["); builder.Append(i); - builder.Append("]"); + builder.Append(']'); return builder.ToString(); } @@ -5620,7 +5620,7 @@ private static string BuildSequenceOfBinaryExpressions_06(int count = 8192) { builder.Append("a["); builder.Append(i); - builder.Append("]"); + builder.Append(']'); builder.Append(" && "); builder.Append("f["); builder.Append(i); @@ -5629,7 +5629,7 @@ private static string BuildSequenceOfBinaryExpressions_06(int count = 8192) builder.Append("a["); builder.Append(i); - builder.Append("]"); + builder.Append(']'); return builder.ToString(); } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index d3e814d26db7a..7f3182aab7847 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -3266,7 +3266,7 @@ static void Main() public void HugeTupleCreationParses() { StringBuilder b = new StringBuilder(); - b.Append("("); + b.Append('('); for (int i = 0; i < 3000; i++) { b.Append("1, "); @@ -3292,7 +3292,7 @@ static void Main() public void HugeTupleDeclarationParses() { StringBuilder b = new StringBuilder(); - b.Append("("); + b.Append('('); for (int i = 0; i < 3000; i++) { b.Append("int, "); diff --git a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests.cs b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests.cs index c6679bed1893f..cbf51c6c062c2 100644 --- a/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Attributes/AttributeTests.cs @@ -5896,9 +5896,9 @@ class A // (35,2): error CS0181: Attribute constructor parameter 'd' has type 'decimal', which is not a valid attribute parameter type // [X(1)] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "X").WithArguments("d", "decimal").WithLocation(35, 2), - // (37,2): error CS0121: The call is ambiguous between the following methods or properties: 'XAttribute.XAttribute(ref int)' and 'XAttribute.XAttribute(e1)' + // (37,2): error CS0121: The call is ambiguous between the following methods or properties: 'XAttribute.XAttribute(decimal)' and 'XAttribute.XAttribute(e1)' // [X(A.dyn)] - Diagnostic(ErrorCode.ERR_AmbigCall, "X(A.dyn)").WithArguments("XAttribute.XAttribute(ref int)", "XAttribute.XAttribute(e1)").WithLocation(37, 2), + Diagnostic(ErrorCode.ERR_AmbigCall, "X(A.dyn)").WithArguments("XAttribute.XAttribute(decimal)", "XAttribute.XAttribute(e1)").WithLocation(37, 2), // (38,2): error CS0181: Attribute constructor parameter 'd' has type 'decimal', which is not a valid attribute parameter type // [X(m.NotAConstant() + 2)] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "X").WithArguments("d", "decimal").WithLocation(38, 2)); diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTest.cs b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTest.cs index c999a17a5372e..5161c2720c398 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTest.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueTest.cs @@ -23,9 +23,11 @@ internal sealed class EditAndContinueTest( { private readonly CSharpCompilationOptions _compilationOptions = (options ?? TestOptions.DebugDll).WithConcurrentBuild(false); private readonly CSharpParseOptions _parseOptions = parseOptions ?? TestOptions.Regular.WithNoRefSafetyRulesAttribute(); + private readonly TargetFramework _targetFramework = targetFramework; + private readonly IEnumerable? _references = references; protected override Compilation CreateCompilation(SyntaxTree tree) - => CSharpTestBase.CreateCompilation(tree, references, options: _compilationOptions, targetFramework: targetFramework); + => CSharpTestBase.CreateCompilation(tree, _references, options: _compilationOptions, targetFramework: _targetFramework); protected override SourceWithMarkedNodes CreateSourceWithMarkedNodes(string source) => EditAndContinueTestBase.MarkedSource(source, options: _parseOptions); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 286611ca8aac9..74f8efa9b607c 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -2764,6 +2764,71 @@ static void Main() Diagnostic(ErrorCode.ERR_BadArgCount, "Local").WithArguments("Local", "2").WithLocation(10, 9)); } + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71399")] + [CompilerTrait(CompilerFeature.Dynamic)] + public void DynamicArgWithRefKind_01() + { + var src = @" +class C +{ + static void Main() + { + dynamic i = 1; + + local1(i); + local1(ref i); + + local2(i); + local3(i); + + void local1(ref int x){ x++; } + void local2(ref object x){ } + void local3(ref dynamic x){ x++; } + } +}"; + VerifyDiagnostics(src, + // (8,16): error CS1620: Argument 1 must be passed with the 'ref' keyword + // local1(i); + Diagnostic(ErrorCode.ERR_BadArgRef, "i").WithArguments("1", "ref").WithLocation(8, 16), + // (9,20): error CS1503: Argument 1: cannot convert from 'ref dynamic' to 'ref int' + // local1(ref i); + Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref dynamic", "ref int").WithLocation(9, 20), + // (11,16): error CS1620: Argument 1 must be passed with the 'ref' keyword + // local2(i); + Diagnostic(ErrorCode.ERR_BadArgRef, "i").WithArguments("1", "ref").WithLocation(11, 16), + // (12,16): error CS1620: Argument 1 must be passed with the 'ref' keyword + // local3(i); + Diagnostic(ErrorCode.ERR_BadArgRef, "i").WithArguments("1", "ref").WithLocation(12, 16) + ); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71399")] + [CompilerTrait(CompilerFeature.Dynamic)] + public void DynamicArgWithRefKind_02() + { + var src = @" +class C +{ + static void Main() + { + dynamic i = 1; + + local2(ref i); + System.Console.Write(i); + local3(ref i); + System.Console.Write(i); + + void local2(ref object x){ ref dynamic y = ref x; y++; } + void local3(ref dynamic x){ x++; } + } +}"; + var comp = CreateCompilation(src, targetFramework: TargetFramework.StandardAndCSharp, options: TestOptions.ReleaseExe); + + CompileAndVerify(comp, expectedOutput: "23").VerifyDiagnostics(); + } + [WorkItem(3923, "https://github.com/dotnet/roslyn/issues/3923")] [Fact] public void ExpressionTreeLocalFunctionUsage_01() diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index ac7d148ba1e11..bdb3dd42a766b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -61751,9 +61751,9 @@ public void Lambda_Nesting_Large_01() builder.Append($" M0(c{depth} => {{ }}"); for (int i = 0; i < depth; i++) { - builder.Append(")"); + builder.Append(')'); } - builder.Append(";"); + builder.Append(';'); var source = @" using System; @@ -64045,7 +64045,7 @@ void local1() void local2() { - F.ToString(); + F.ToString(); // 2 } } } @@ -64059,7 +64059,10 @@ void local2() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F").WithLocation(10, 13), // (13,14): warning CS8321: The local function 'local2' is declared but never used // void local2() - Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local2").WithArguments("local2").WithLocation(13, 14)); + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local2").WithArguments("local2").WithLocation(13, 14), + // (15,13): warning CS8602: Dereference of a possibly null reference. + // F.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F").WithLocation(15, 13)); } [Fact] @@ -64126,6 +64129,339 @@ void local2() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F").WithLocation(18, 13)); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_SetInOneFunction() + { + var source = """ + #nullable enable + class C + { + string? F; + void M() + { + local2(); + + void local1() + { + F.ToString(); + } + + void local2() + { + F = ""; + local1(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_SetInOneFunction_02([CombinatorialValues("class", "struct")] string kind) + { + var source = $$""" + #nullable enable + {{kind}} S + { + string? F; + void M() + { + var s = this; + local2(); + + void local1() + { + s.F.ToString(); + } + + void local2() + { + s.F = ""; + local1(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_SetInOneFunction_Loop() + { + var source = """ + #nullable enable + class C + { + string? F; + void M() + { + local2(); + + void local1() + { + for (int i = 0; i < 3; i++) { } + F.ToString(); + } + + void local2() + { + F = ""; + local1(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_SetInOneFunction_AllocateSlot() + { + var source = """ + #nullable enable + class C + { + string? F; + void M() + { + F = null; + local2(); + + void local1() + { + F.ToString(); + } + + void local2() + { + F = ""; + local1(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_SetInOneFunction_Nested([CombinatorialValues("class", "struct")] string kind) + { + var value = kind == "struct" ? ".Value" : ""; + var source = $$""" + #nullable enable + {{kind}} D + { + public string? DF; + } + + class C + { + D? F; + void M() + { + local2(); + + void local1() + { + F{{value}}.DF.ToString(); + } + + void local2() + { + F = new() { DF = "" }; + local1(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_SetInOneFunction_Nested_02( + [CombinatorialValues("class", "struct")] string kind1, + [CombinatorialValues("class", "struct")] string kind2) + { + var value = kind1 == "struct" ? ".Value" : ""; + var source = $$""" + #nullable enable + {{kind1}} D + { + public string? DF; + } + + {{kind2}} C + { + D? F; + void M() + { + var c = this; + local2(); + + void local1() + { + c.F{{value}}.DF.ToString(); + } + + void local2() + { + c.F = new() { DF = "" }; + local1(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics(); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_Unreachable(bool allocateSlot, bool loop) + { + var source = $$""" + #nullable enable + #pragma warning disable CS0649 // field not assigned + class C + { + string? F; + void M() + { + string? s = "a"; + {{(allocateSlot ? "F = null;" : "")}} + + void local() + { + {{(loop ? "for (int i = 0; i < 3; i++) { }" : "")}} + + F.ToString(); + s.ToString(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics( + // (11,14): warning CS8321: The local function 'local' is declared but never used + // void local() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(11, 14), + // (15,13): warning CS8602: Dereference of a possibly null reference. + // F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F").WithLocation(15, 13)); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_Member_Unreachable_SelfCall(bool allocateSlot, bool loop) + { + var source = $$""" + #nullable enable + #pragma warning disable CS0649 // field not assigned + class C + { + string? F; + void M() + { + string? s = "a"; + {{(allocateSlot ? "F = null;" : "")}} + + void local() + { + {{(loop ? "for (int i = 0; i < 3; i++) { }" : "")}} + + F.ToString(); + s.ToString(); + + s = null; + local(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics( + // (15,13): warning CS8602: Dereference of a possibly null reference. + // F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F").WithLocation(15, 13), + // (16,13): warning CS8602: Dereference of a possibly null reference. + // s.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(16, 13)); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_UnreachableGraph_01(bool allocateSlot) + { + var source = $$""" + #nullable enable + class C + { + string? F; + void M() + { + string? s = null; + {{(allocateSlot ? "F = null;" : "")}} + + void local1() + { + for (int i = 0; i < 3; i++) { } + + F.ToString(); + s.ToString(); + } + + void local2() + { + F = "a"; + s = "b"; + local1(); + } + } + } + """; + // Notice the warning which is not present when the local funcs are swapped (cf. LocalFunction_UnreachableGraph_02). + // That is because we try to visit used functions first but we cannot see into call graphs unreachable from the outside. + // This is acceptable as it happens only for unreachable code. + CreateCompilation(source).VerifyDiagnostics( + // (14,13): warning CS8602: Dereference of a possibly null reference. + // F.ToString(); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F").WithLocation(14, 13), + // (18,14): warning CS8321: The local function 'local2' is declared but never used + // void local2() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local2").WithArguments("local2").WithLocation(18, 14)); + } + + [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/71419")] + public void LocalFunction_UnreachableGraph_02(bool allocateSlot) + { + var source = $$""" + #nullable enable + class C + { + string? F; + void M() + { + string? s = null; + {{(allocateSlot ? "F = null;" : "")}} + + void local1() + { + F = "a"; + s = "b"; + local2(); + } + + void local2() + { + for (int i = 0; i < 3; i++) { } + + F.ToString(); + s.ToString(); + } + } + } + """; + CreateCompilation(source).VerifyDiagnostics( + // (10,14): warning CS8321: The local function 'local1' is declared but never used + // void local1() + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local1").WithArguments("local1").WithLocation(10, 14)); + } + [Fact] public void New_01() { @@ -109642,7 +109978,10 @@ void g() comp.VerifyDiagnostics( // (12,21): warning CS8602: Dereference of a possibly null reference. // int n = this.F.Length; // 1 - Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "this.F").WithLocation(12, 21)); + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "this.F").WithLocation(12, 21), + // (18,21): warning CS8602: Dereference of a possibly null reference. + // int n = base.F.Length; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "base.F").WithLocation(18, 21)); } [WorkItem(31620, "https://github.com/dotnet/roslyn/issues/31620")] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs index 02dbd2001b96d..d74969e7e8ad7 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs @@ -2826,14 +2826,14 @@ static void Main(string[] args) var d = /**/new Dictionary() { {""s"", 1 }, - var x = 1/**/; - } + var x = 1; + }/**/ } "; string expectedOperationTree = @" -IInvalidOperation (OperationKind.Invalid, Type: Dictionary, IsInvalid) (Syntax: 'new Diction ... /**/') +IInvalidOperation (OperationKind.Invalid, Type: Dictionary, IsInvalid) (Syntax: 'new Diction ... }') Children(1): - IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: Dictionary, IsInvalid) (Syntax: '{ ... /**/') + IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: Dictionary, IsInvalid) (Syntax: '{ ... }') Initializers(3): IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: '{""s"", 1 }') Children(2): @@ -2842,33 +2842,39 @@ static void Main(string[] args) IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'var') Children(0) ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'x = 1') - Left: + Left: IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: 'x') Children(1): IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'x') Children(1): IInstanceReferenceOperation (ReferenceKind: ImplicitReceiver) (OperationKind.InstanceReference, Type: Dictionary, IsInvalid, IsImplicit) (Syntax: 'Dictionary< ... ct, object>') - Right: - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') + Right: + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { - // CS1003: Syntax error, ',' expected - // var x = 1/**/; + // (9,13): error CS1003: Syntax error, ',' expected + // var x = 1; Diagnostic(ErrorCode.ERR_SyntaxError, "x").WithArguments(",").WithLocation(9, 13), - // CS1513: } expected - // var x = 1/**/; - Diagnostic(ErrorCode.ERR_RbraceExpected, ";").WithLocation(9, 29), - // CS0246: The type or namespace name 'Dictionary<,>' could not be found (are you missing a using directive or an assembly reference?) + // (9,18): error CS1003: Syntax error, ',' expected + // var x = 1; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(9, 18), + // (10,6): error CS1002: ; expected + // }/**/ + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(10, 6), + // (11,2): error CS1513: } expected + // } + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(11, 2), + // (6,31): error CS0246: The type or namespace name 'Dictionary<,>' could not be found (are you missing a using directive or an assembly reference?) // var d = /**/new Dictionary() Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Dictionary").WithArguments("Dictionary<,>").WithLocation(6, 31), - // CS0747: Invalid initializer member declarator + // (8,13): error CS0747: Invalid initializer member declarator // {"s", 1 }, Diagnostic(ErrorCode.ERR_InvalidInitializerElementInitializer, @"{""s"", 1 }").WithLocation(8, 13), - // CS0103: The name 'var' does not exist in the current context - // var x = 1/**/; + // (9,9): error CS0103: The name 'var' does not exist in the current context + // var x = 1; Diagnostic(ErrorCode.ERR_NameNotInContext, "var").WithArguments("var").WithLocation(9, 9), - // CS0747: Invalid initializer member declarator - // var x = 1/**/; + // (9,9): error CS0747: Invalid initializer member declarator + // var x = 1; Diagnostic(ErrorCode.ERR_InvalidInitializerElementInitializer, "var").WithLocation(9, 9) }; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionPerfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionPerfTests.cs index b70642d750407..40cf855b54633 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionPerfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OverloadResolutionPerfTests.cs @@ -679,7 +679,7 @@ class C sourceBuilder.Append(" "); for (var i = 0; i < 15; i++) { - sourceBuilder.Append(")"); + sourceBuilder.Append(')'); } sourceBuilder.Append(source2); diff --git a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverFuzzTests.cs b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverFuzzTests.cs index b047a72f6e24f..289038a3eb3e5 100644 --- a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverFuzzTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverFuzzTests.cs @@ -23,6 +23,8 @@ using Xunit; using Xunit.Abstractions; +#pragma warning disable RS0062 // Do not implicitly capture primary constructor parameters + namespace Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.SourceGeneration { public class GeneratorDriverFuzzTests diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 0498452e056c9..d8dbb3d409388 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -2405,7 +2405,69 @@ static void Main() compilation.VerifyEmitDiagnostics( // (9,27): error CS0656: Missing compiler required member 'System.Object.ToString' // Console.WriteLine(c + "3"); - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"c + ""3""").WithArguments("System.Object", "ToString").WithLocation(9, 27) + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "c").WithArguments("System.Object", "ToString").WithLocation(9, 27) + ); + } + + [Fact] + public void System_Object__ToString_3Args() + { + var source = """ + using System; + + public class Test + { + static void Main() + { + char c = 'c'; + int i = 2; + Console.WriteLine(c + "3" + i); + } + } + """; + + var compilation = CreateCompilationWithMscorlib45(source); + compilation.MakeMemberMissing(SpecialMember.System_Object__ToString); + compilation.VerifyEmitDiagnostics( + // (9,27): error CS0656: Missing compiler required member 'System.Object.ToString' + // Console.WriteLine(c + "3" + i); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "c").WithArguments("System.Object", "ToString").WithLocation(9, 27), + // (9,37): error CS0656: Missing compiler required member 'System.Object.ToString' + // Console.WriteLine(c + "3" + i); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "i").WithArguments("System.Object", "ToString").WithLocation(9, 37) + ); + } + + [Fact] + public void System_Object__ToString_4Args() + { + var source = """ + using System; + + public class Test + { + static void Main() + { + char c = 'c'; + int i = 2; + double d = 0.7; + Console.WriteLine(c + "3" + i + d); + } + } + """; + + var compilation = CreateCompilationWithMscorlib45(source); + compilation.MakeMemberMissing(SpecialMember.System_Object__ToString); + compilation.VerifyEmitDiagnostics( + // (10,27): error CS0656: Missing compiler required member 'System.Object.ToString' + // Console.WriteLine(c + "3" + i + d); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "c").WithArguments("System.Object", "ToString").WithLocation(10, 27), + // (10,37): error CS0656: Missing compiler required member 'System.Object.ToString' + // Console.WriteLine(c + "3" + i + d); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "i").WithArguments("System.Object", "ToString").WithLocation(10, 37), + // (10,41): error CS0656: Missing compiler required member 'System.Object.ToString' + // Console.WriteLine(c + "3" + i + d); + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "d").WithArguments("System.Object", "ToString").WithLocation(10, 41) ); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockSymbolTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockSymbolTests.cs index 4cdcecb7b7549..a8983f85d6f85 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockSymbolTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockSymbolTests.cs @@ -167,7 +167,7 @@ orderby c.Name builder.Append(" "); } - builder.Append("}"); + builder.Append('}'); } } diff --git a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DocumentationCommentLexerTestBase.cs b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DocumentationCommentLexerTestBase.cs index 2406a9ca1c28b..5d9c2d7deb76b 100644 --- a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DocumentationCommentLexerTestBase.cs +++ b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DocumentationCommentLexerTestBase.cs @@ -99,7 +99,7 @@ private static string ToExpectedTokenString(InternalSyntax.SyntaxToken token) } } - builder.Append(")"); + builder.Append(')'); return builder.ToString(); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index 10edbc2ce7455..108878af7c079 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -6735,7 +6735,7 @@ public void TooDeepObjectInitializerAsExpression() builder.AppendLine("}, u = 0"); } - builder.Append(@"}"); + builder.Append('}'); var expr = SyntaxFactory.ParseExpression(builder.ToString()); var actualErrors = expr.GetDiagnostics().ToArray(); @@ -6762,7 +6762,7 @@ public void TooDeepObjectInitializerAsStatement() builder.AppendLine("}, u = 0"); } - builder.Append(@"}"); + builder.Append('}'); var stmt = SyntaxFactory.ParseStatement(builder.ToString()); var actualErrors = stmt.GetDiagnostics().ToArray(); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs index 9cbdc4d5fcbf9..82ccfd5192fb8 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs @@ -4926,8 +4926,11 @@ public void TestSemicolonAfterObjectInitializerStart() Assert.NotEqual(SyntaxKind.None, ds.Declaration.Variables[0].Initializer.EqualsToken.Kind()); Assert.NotNull(ds.Declaration.Variables[0].Initializer.Value); Assert.Equal(SyntaxKind.ObjectCreationExpression, ds.Declaration.Variables[0].Initializer.Value.Kind()); - Assert.Equal(1, file.Errors().Length); - Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[0].Code); + Assert.Equal(4, file.Errors().Length); + Assert.Equal((int)ErrorCode.ERR_InvalidExprTerm, file.Errors()[0].Code); + Assert.Equal((int)ErrorCode.ERR_SyntaxError, file.Errors()[1].Code); + Assert.Equal((int)ErrorCode.ERR_SemicolonExpected, file.Errors()[2].Code); + Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[3].Code); } [Fact] @@ -4953,8 +4956,10 @@ public void TestSemicolonAfterObjectInitializerMemberStart() Assert.NotEqual(SyntaxKind.None, ds.Declaration.Variables[0].Initializer.EqualsToken.Kind()); Assert.NotNull(ds.Declaration.Variables[0].Initializer.Value); Assert.Equal(SyntaxKind.ObjectCreationExpression, ds.Declaration.Variables[0].Initializer.Value.Kind()); - Assert.Equal(1, file.Errors().Length); - Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[0].Code); + Assert.Equal(3, file.Errors().Length); + Assert.Equal((int)ErrorCode.ERR_SyntaxError, file.Errors()[0].Code); + Assert.Equal((int)ErrorCode.ERR_SemicolonExpected, file.Errors()[1].Code); + Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[2].Code); } [Fact] @@ -4980,9 +4985,11 @@ public void TestSemicolonAfterObjectInitializerMemberEquals() Assert.NotEqual(SyntaxKind.None, ds.Declaration.Variables[0].Initializer.EqualsToken.Kind()); Assert.NotNull(ds.Declaration.Variables[0].Initializer.Value); Assert.Equal(SyntaxKind.ObjectCreationExpression, ds.Declaration.Variables[0].Initializer.Value.Kind()); - Assert.Equal(2, file.Errors().Length); + Assert.Equal(4, file.Errors().Length); Assert.Equal((int)ErrorCode.ERR_InvalidExprTerm, file.Errors()[0].Code); - Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[1].Code); + Assert.Equal((int)ErrorCode.ERR_SyntaxError, file.Errors()[1].Code); + Assert.Equal((int)ErrorCode.ERR_SemicolonExpected, file.Errors()[2].Code); + Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[3].Code); } [Fact] @@ -5008,8 +5015,634 @@ public void TestSemicolonAfterObjectInitializerMember() Assert.NotEqual(SyntaxKind.None, ds.Declaration.Variables[0].Initializer.EqualsToken.Kind()); Assert.NotNull(ds.Declaration.Variables[0].Initializer.Value); Assert.Equal(SyntaxKind.ObjectCreationExpression, ds.Declaration.Variables[0].Initializer.Value.Kind()); - Assert.Equal(1, file.Errors().Length); - Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[0].Code); + Assert.Equal(3, file.Errors().Length); + Assert.Equal((int)ErrorCode.ERR_SyntaxError, file.Errors()[0].Code); + Assert.Equal((int)ErrorCode.ERR_SemicolonExpected, file.Errors()[1].Code); + Assert.Equal((int)ErrorCode.ERR_RbraceExpected, file.Errors()[2].Code); + } + + [Fact] + public void TestSemicolonAfterObjectInitializerMember2() + { + var text = "class c { void m() { var x = new C { a = b; }; var y = 5; } }"; + + UsingTree(text, + // (1,43): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 43)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "c"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "m"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "y"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestSemicolonAfterObjectInitializerMember3() + { + var text = "class c { void m() { var x = new C { a = b; c = d, e = f; g = h }; var y = 5; } }"; + + UsingTree(text, + // (1,43): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b; c = d, e = f; g = h }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 43), + // (1,57): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b; c = d, e = f; g = h }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 57)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "c"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "m"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "d"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "f"); + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "g"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "h"); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "y"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestSemicolonAfterObjectInitializerMember4() + { + var text = "class c { void m() { var x = new C { a = b; }; if (true) return; } }"; + + UsingTree(text, + // (1,43): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b; }; if (true) return; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 43)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "c"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "m"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.IfStatement); + { + N(SyntaxKind.IfKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.ReturnStatement); + { + N(SyntaxKind.ReturnKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestSemicolonAfterObjectInitializerMember5() + { + var text = "class c { void m() { var x = new C { a = b; if (true) return; }; var y = 5; } }"; + + UsingTree(text, + // (1,43): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b; if (true) return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 43), + // (1,45): error CS1513: } expected + // class c { void m() { var x = new C { a = b; if (true) return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_RbraceExpected, "if").WithLocation(1, 45), + // (1,45): error CS1002: ; expected + // class c { void m() { var x = new C { a = b; if (true) return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "if").WithLocation(1, 45), + // (1,64): error CS1597: Semicolon after method or accessor block is not valid + // class c { void m() { var x = new C { a = b; if (true) return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_UnexpectedSemicolon, ";").WithLocation(1, 64), + // (1,79): error CS1022: Type or namespace definition, or end-of-file expected + // class c { void m() { var x = new C { a = b; if (true) return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(1, 79)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "c"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "m"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + M(SyntaxKind.CloseBraceToken); + } + } + } + } + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.IfStatement); + { + N(SyntaxKind.IfKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + N(SyntaxKind.CloseParenToken); + N(SyntaxKind.ReturnStatement); + { + N(SyntaxKind.ReturnKeyword); + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "y"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestSemicolonAfterObjectInitializerMember6() + { + var text = "class c { void m() { var x = new C { a = b; return; }; var y = 5; } }"; + + UsingTree(text, + // (1,43): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b; return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 43), + // (1,45): error CS1513: } expected + // class c { void m() { var x = new C { a = b; return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_RbraceExpected, "return").WithLocation(1, 45), + // (1,45): error CS1002: ; expected + // class c { void m() { var x = new C { a = b; return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "return").WithLocation(1, 45), + // (1,54): error CS1597: Semicolon after method or accessor block is not valid + // class c { void m() { var x = new C { a = b; return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_UnexpectedSemicolon, ";").WithLocation(1, 54), + // (1,69): error CS1022: Type or namespace definition, or end-of-file expected + // class c { void m() { var x = new C { a = b; return; }; var y = 5; } } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(1, 69)); + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "c"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "m"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.ObjectCreationExpression); + { + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.ObjectInitializerExpression); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SimpleAssignmentExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.EqualsToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.SemicolonToken); + M(SyntaxKind.CloseBraceToken); + } + } + } + } + } + M(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.ReturnStatement); + { + N(SyntaxKind.ReturnKeyword); + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.FieldDeclaration); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "y"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); } [Fact] @@ -5037,9 +5670,18 @@ public void TestSemicolonAfterObjectInitializerMemberComma() Assert.Equal(SyntaxKind.ObjectCreationExpression, ds.Declaration.Variables[0].Initializer.Value.Kind()); file.GetDiagnostics().Verify( - // (1,45): error CS1513: } expected + // (1,45): error CS1525: Invalid expression term ';' + // class c { void m() { var x = new C { a = b, ; } } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(1, 45), + // (1,45): error CS1003: Syntax error, ',' expected + // class c { void m() { var x = new C { a = b, ; } } + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(1, 45), + // (1,49): error CS1002: ; expected + // class c { void m() { var x = new C { a = b, ; } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "}").WithLocation(1, 49), + // (1,50): error CS1513: } expected // class c { void m() { var x = new C { a = b, ; } } - Diagnostic(ErrorCode.ERR_RbraceExpected, ";").WithLocation(1, 45)); + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(1, 50)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs index cfc1c343f5936..0f33ab868b05d 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs @@ -455,6 +455,1722 @@ public void TestErrantCaseInSwitchExpression3() EOF(); } + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + [InlineData("case")] + [InlineData("// leading\r\ncase")] + [InlineData("/*leading*/ case")] + [InlineData("case // trailing")] + [InlineData("case /* trailing */")] + [InlineData("case /* trailing\r\n*/")] + [InlineData("/*leading*/ case // trailing")] + [InlineData("/*leading*/ case /* trailing */")] + public void TestErrantCaseInSwitchExpression4(string caseString) + { + UsingTree($$""" + class C + { + public static int X() + => 5 switch + { + {{caseString}} + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case"), + // (6,17): error CS8504: Pattern missing + // case + Diagnostic(ErrorCode.ERR_MissingPattern, ""), + // (6,17): error CS1003: Syntax error, '=>' expected + // case + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>"), + // (6,17): error CS1525: Invalid expression term '}' + // case + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}")); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression5() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case, + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case, + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,17): error CS8504: Pattern missing + // case, + Diagnostic(ErrorCode.ERR_MissingPattern, ",").WithLocation(6, 17), + // (6,17): error CS1003: Syntax error, '=>' expected + // case, + Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments("=>").WithLocation(6, 17), + // (6,17): error CS1525: Invalid expression term ',' + // case, + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(6, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression6() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case; + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case; + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,17): error CS8504: Pattern missing + // case; + Diagnostic(ErrorCode.ERR_MissingPattern, ";").WithLocation(6, 17), + // (6,17): error CS1003: Syntax error, '=>' expected + // case; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("=>").WithLocation(6, 17), + // (6,17): error CS1525: Invalid expression term ';' + // case; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(6, 17), + // (6,17): error CS1003: Syntax error, ',' expected + // case; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(6, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression7() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case => + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case => + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,18): error CS8504: Pattern missing + // case => + Diagnostic(ErrorCode.ERR_MissingPattern, "=>").WithLocation(6, 18), + // (6,20): error CS1525: Invalid expression term '}' + // case => + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 20)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression8() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case when true + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case when true + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,23): error CS1003: Syntax error, '=>' expected + // case when true + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=>").WithLocation(6, 23)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression9() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case when true => + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case when true => + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,23): error CS1003: Syntax error, '=>' expected + // case when true => + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=>").WithLocation(6, 23), + // (6,28): error CS1003: Syntax error, ',' expected + // case when true => + Diagnostic(ErrorCode.ERR_SyntaxError, "=>").WithArguments(",").WithLocation(6, 28), + // (6,28): error CS8504: Pattern missing + // case when true => + Diagnostic(ErrorCode.ERR_MissingPattern, "=>").WithLocation(6, 28), + // (6,30): error CS1525: Invalid expression term '}' + // case when true => + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 30)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression10() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case true => + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case true => + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,25): error CS1525: Invalid expression term '}' + // case true => + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 25)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression11() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case when + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case when + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,22): error CS1003: Syntax error, '=>' expected + // case when + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>").WithLocation(6, 22), + // (6,22): error CS1525: Invalid expression term '}' + // case when + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 22)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression12() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + case when => + }; + } + """, + // (6,13): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // case when => + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 13), + // (6,25): error CS1525: Invalid expression term '}' + // case when => + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 25)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression13() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when case + }; + } + """, + // (6,18): error CS1003: Syntax error, '=>' expected + // when case + Diagnostic(ErrorCode.ERR_SyntaxError, "case").WithArguments("=>").WithLocation(6, 18), + // (6,18): error CS1525: Invalid expression term 'case' + // when case + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "case").WithArguments("case").WithLocation(6, 18), + // (6,18): error CS1003: Syntax error, ',' expected + // when case + Diagnostic(ErrorCode.ERR_SyntaxError, "case").WithArguments(",").WithLocation(6, 18), + // (6,18): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // when case + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 18), + // (6,22): error CS8504: Pattern missing + // when case + Diagnostic(ErrorCode.ERR_MissingPattern, "").WithLocation(6, 22), + // (6,22): error CS1003: Syntax error, '=>' expected + // when case + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>").WithLocation(6, 22), + // (6,22): error CS1525: Invalid expression term '}' + // when case + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 22)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CommaToken); + M(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantCaseInSwitchExpression14() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when case 0 + }; + } + """, + // (6,18): error CS1003: Syntax error, '=>' expected + // when case 0 + Diagnostic(ErrorCode.ERR_SyntaxError, "case").WithArguments("=>").WithLocation(6, 18), + // (6,18): error CS1525: Invalid expression term 'case' + // when case 0 + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "case").WithArguments("case").WithLocation(6, 18), + // (6,18): error CS1003: Syntax error, ',' expected + // when case 0 + Diagnostic(ErrorCode.ERR_SyntaxError, "case").WithArguments(",").WithLocation(6, 18), + // (6,18): error CS9134: A switch expression arm does not begin with a 'case' keyword. + // when case 0 + Diagnostic(ErrorCode.ERR_BadCaseInSwitchArm, "case").WithLocation(6, 18), + // (6,24): error CS1003: Syntax error, '=>' expected + // when case 0 + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>").WithLocation(6, 24), + // (6,24): error CS1525: Invalid expression term '}' + // when case 0 + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 24)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression1() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when + }; + } + """, + // (6,17): error CS1003: Syntax error, '=>' expected + // when + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>").WithLocation(6, 17), + // (6,17): error CS1525: Invalid expression term '}' + // when + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression2() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when, + }; + } + """, + // (6,17): error CS1003: Syntax error, '=>' expected + // when, + Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments("=>").WithLocation(6, 17), + // (6,17): error CS1525: Invalid expression term ',' + // when, + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(6, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression3() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when; + }; + } + """, + // (6,17): error CS1003: Syntax error, '=>' expected + // when; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments("=>").WithLocation(6, 17), + // (6,17): error CS1525: Invalid expression term ';' + // when; + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(6, 17), + // (6,17): error CS1003: Syntax error, ',' expected + // when; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(6, 17)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression4() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when => + }; + } + """, + // (6,20): error CS1525: Invalid expression term '}' + // when => + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 20)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression5() + { + // No parse error here. `when` is a legal `constant pattern`. + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when => true + }; + } + """); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression6() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when true + }; + } + """, + // (6,18): error CS1003: Syntax error, '=>' expected + // when true + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=>").WithLocation(6, 18)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression7() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when true, + }; + } + """, + // (6,18): error CS1003: Syntax error, '=>' expected + // when true, + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=>").WithLocation(6, 18)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression8() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when true; + }; + } + """, + // (6,18): error CS1003: Syntax error, '=>' expected + // when true; + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=>").WithLocation(6, 18), + // (6,22): error CS1003: Syntax error, ',' expected + // when true; + Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(",").WithLocation(6, 22)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71957")] + public void TestErrantWhenInSwitchExpression9() + { + UsingTree(""" + class C + { + public static int X() + => 5 switch + { + when true => + }; + } + """, + // (6,18): error CS1003: Syntax error, '=>' expected + // when true => + Diagnostic(ErrorCode.ERR_SyntaxError, "true").WithArguments("=>").WithLocation(6, 18), + // (6,23): error CS1003: Syntax error, ',' expected + // when true => + Diagnostic(ErrorCode.ERR_SyntaxError, "=>").WithArguments(",").WithLocation(6, 23), + // (6,23): error CS8504: Pattern missing + // when true => + Diagnostic(ErrorCode.ERR_MissingPattern, "=>").WithLocation(6, 23), + // (6,25): error CS1525: Invalid expression term '}' + // when true => + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(6, 25)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PublicKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "X"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ArrowExpressionClause); + { + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "5"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "when"); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.TrueLiteralExpression); + { + N(SyntaxKind.TrueKeyword); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + [Fact] public void TestErrantColonsInSwitchExpression1() { diff --git a/src/Compilers/CSharp/Test/WinRT/Metadata/WinMdDumpTest.cs b/src/Compilers/CSharp/Test/WinRT/Metadata/WinMdDumpTest.cs index c5897b3a8f8bb..10a173b227b57 100644 --- a/src/Compilers/CSharp/Test/WinRT/Metadata/WinMdDumpTest.cs +++ b/src/Compilers/CSharp/Test/WinRT/Metadata/WinMdDumpTest.cs @@ -60,7 +60,7 @@ private void AppendMembers(StringBuilder result, NamespaceOrTypeSymbol container result.Append(memberIndent); result.Append(".class "); MetadataSignatureHelper.AppendTypeAttributes(result, namedType.Flags); - result.Append(" "); + result.Append(' '); result.Append(member); if ((object)namedType.BaseType() != null) @@ -110,10 +110,10 @@ private void AppendMembers(StringBuilder result, NamespaceOrTypeSymbol container result.Append(".field "); MetadataSignatureHelper.AppendFieldAttributes(result, field.Flags); - result.Append(" "); + result.Append(' '); result.Append(field.TypeWithAnnotations); - result.Append(" "); + result.Append(' '); result.Append(member.Name); result.AppendLine(); @@ -131,11 +131,11 @@ private void AppendMembers(StringBuilder result, NamespaceOrTypeSymbol container ((PEModuleSymbol)container.ContainingModule).Module.GetPropertyDefPropsOrThrow(property.Handle, out propertyName, out propertyAttrs); if (MetadataSignatureHelper.AppendPropertyAttributes(result, propertyAttrs)) { - result.Append(" "); + result.Append(' '); } result.Append(property.TypeWithAnnotations); - result.Append(" "); + result.Append(' '); result.Append(property.Name); result.AppendLine(); @@ -175,16 +175,16 @@ private void AppendMembers(StringBuilder result, NamespaceOrTypeSymbol container if (MetadataSignatureHelper.AppendEventAttributes(result, eventAttrs)) { - result.Append(" "); + result.Append(' '); } result.Append(evnt.TypeWithAnnotations); - result.Append(" "); + result.Append(' '); result.Append(evnt.Name); result.AppendLine(); result.Append(memberIndent); - result.Append("{"); + result.Append('{'); result.AppendLine(); AppendCustomAttributes(result, member, memberIndent, inBlock: true); @@ -240,7 +240,7 @@ private static void AppendCustomAttributes(StringBuilder result, Symbol symbol, { result.Append("[Missing: "); result.Append(attribute.AttributeClass); - result.Append("]"); + result.Append(']'); } else { @@ -274,7 +274,7 @@ private static void AppendCustomAttributes(StringBuilder result, Symbol symbol, i++; } - result.Append(")"); + result.Append(')'); result.AppendLine(); } @@ -290,7 +290,7 @@ private static void AppendConstant(StringBuilder result, TypedConstant constant) switch (constant.Kind) { case TypedConstantKind.Array: - result.Append("{"); + result.Append('{'); int i = 0; foreach (var item in constant.Values) @@ -303,13 +303,13 @@ private static void AppendConstant(StringBuilder result, TypedConstant constant) AppendConstant(result, item); } - result.Append("}"); + result.Append('}'); break; case TypedConstantKind.Type: result.Append("typeof("); result.Append(constant.Value); - result.Append(")"); + result.Append(')'); break; case TypedConstantKind.Enum: @@ -317,9 +317,9 @@ private static void AppendConstant(StringBuilder result, TypedConstant constant) var value = constant.Value; if (value.GetType() == typeof(string)) { - result.Append("\""); + result.Append('"'); result.Append(value); - result.Append("\""); + result.Append('"'); } else if (value.GetType() == typeof(bool)) { @@ -339,9 +339,9 @@ private static void AppendConstant(StringBuilder result, TypedConstant constant) private static void AppendMethod(StringBuilder result, PEMethodSymbol method, string indent, bool includeTypeName = false) { MetadataSignatureHelper.AppendMethodAttributes(result, method.Flags); - result.Append(" "); + result.Append(' '); AppendSignatureType(result, method.ReturnType, RefKind.None); - result.Append(" "); + result.Append(' '); if (includeTypeName) { @@ -351,7 +351,7 @@ private static void AppendMethod(StringBuilder result, PEMethodSymbol method, st result.Append(method.Name); - result.Append("("); + result.Append('('); bool hasParameterAttributes = false; int i = 0; @@ -369,11 +369,11 @@ private static void AppendMethod(StringBuilder result, PEMethodSymbol method, st if (MetadataSignatureHelper.AppendParameterAttributes(result, parameter.Flags, all: true)) { - result.Append(" "); + result.Append(' '); } AppendSignatureType(result, parameter.Type, parameter.RefKind); - result.Append(" "); + result.Append(' '); result.Append(parameter.Name); i++; } @@ -419,7 +419,7 @@ private static void AppendSignatureType(StringBuilder result, TypeSymbol type, R if (refKind != RefKind.None) { - result.Append("&"); + result.Append('&'); } } diff --git a/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs b/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs index 317d4f221713a..63341865aa107 100644 --- a/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs +++ b/src/Compilers/Core/CodeAnalysisTest/MetadataReferences/MetadataHelpersTests.cs @@ -116,7 +116,7 @@ private static string[] GenerateTypeNamesToDecode(TypeNameConfig[] typeNameConfi TypeNameConfig typeNameConfig = typeNameConfigs[index]; string expectedTopLevelTypeName = "X"; - typeNameBuilder.Append("X"); + typeNameBuilder.Append('X'); string[] expectedNestedTypes = null; if (typeNameConfig.NestingLevel > 0) @@ -149,7 +149,7 @@ private static string[] GenerateTypeNamesToDecode(TypeNameConfig[] typeNameConfi expectedNestedTypes[typeNameConfig.NestingLevel - 1] += genericArityStr; } - typeNameBuilder.Append("["); + typeNameBuilder.Append('['); for (int i = 0; i < genericParamsToDecode.Length; i++) { @@ -160,9 +160,9 @@ private static string[] GenerateTypeNamesToDecode(TypeNameConfig[] typeNameConfi if (typeNameConfig.GenericParamsConfig[i].AssemblyQualified) { - typeNameBuilder.Append("["); + typeNameBuilder.Append('['); typeNameBuilder.Append(genericParamsToDecode[i]); - typeNameBuilder.Append("]"); + typeNameBuilder.Append(']'); } else { @@ -170,7 +170,7 @@ private static string[] GenerateTypeNamesToDecode(TypeNameConfig[] typeNameConfi } } - typeNameBuilder.Append("]"); + typeNameBuilder.Append(']'); } int expectedPointerCount = typeNameConfig.PointerCount; diff --git a/src/Compilers/Core/MSBuildTask/Csc.cs b/src/Compilers/Core/MSBuildTask/Csc.cs index ad9be74ea130b..d4cde85cf8e7a 100644 --- a/src/Compilers/Core/MSBuildTask/Csc.cs +++ b/src/Compilers/Core/MSBuildTask/Csc.cs @@ -456,7 +456,7 @@ void appendGlobalReference(string? itemSpec) // the outgoing string. if (finalDefineConstants.Length > 0) { - finalDefineConstants.Append(";"); + finalDefineConstants.Append(';'); } finalDefineConstants.Append(singleIdentifier); diff --git a/src/Compilers/Core/MSBuildTask/GenerateMSBuildEditorConfig.cs b/src/Compilers/Core/MSBuildTask/GenerateMSBuildEditorConfig.cs index a6b2f77ccfa03..0174f6edc250c 100644 --- a/src/Compilers/Core/MSBuildTask/GenerateMSBuildEditorConfig.cs +++ b/src/Compilers/Core/MSBuildTask/GenerateMSBuildEditorConfig.cs @@ -85,7 +85,7 @@ public override bool Execute() { // write the section for this item builder.AppendLine() - .Append("["); + .Append('['); EncodeString(builder, group.Key); builder.AppendLine("]"); @@ -97,7 +97,7 @@ public override bool Execute() { builder.Append("build_metadata.") .Append(itemType) - .Append(".") + .Append('.') .Append(metadataName) .Append(" = ") .AppendLine(item.GetMetadata(metadataName)); @@ -148,7 +148,7 @@ private static void EncodeString(StringBuilder builder, string value) { if (c is '*' or '?' or '{' or ',' or ';' or '}' or '[' or ']' or '#' or '!') { - builder.Append("\\"); + builder.Append('\\'); } builder.Append(c); } diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs index 8c14035b2cdc3..95bdff05062b1 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics.Tracing; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { @@ -38,12 +37,95 @@ private CodeAnalysisEventSource() { } internal void StartSingleGeneratorRunTime(string generatorName, string assemblyPath, string id) => WriteEvent(3, generatorName, assemblyPath, id); [Event(4, Message = "Generator {0} ran for {2} ticks", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.SingleGeneratorRunTime)] - internal void StopSingleGeneratorRunTime(string generatorName, string assemblyPath, long elapsedTicks, string id) => WriteEvent(4, generatorName, assemblyPath, elapsedTicks, id); + internal unsafe void StopSingleGeneratorRunTime(string generatorName, string assemblyPath, long elapsedTicks, string id) + { + if (IsEnabled()) + { + fixed (char* generatorNameBytes = generatorName) + fixed (char* assemblyPathBytes = assemblyPath) + fixed (char* idBytes = id) + { + Span data = stackalloc EventData[] + { + GetEventDataForString(generatorName, generatorNameBytes), + GetEventDataForString(assemblyPath, assemblyPathBytes), + GetEventDataForInt64(&elapsedTicks), + GetEventDataForString(id, idBytes), + }; + + fixed (EventSource.EventData* dataPtr = data) + { + WriteEventCore(eventId: 4, data.Length, dataPtr); + } + } + } + } [Event(5, Message = "Generator '{0}' failed with exception: {1}", Level = EventLevel.Error)] internal void GeneratorException(string generatorName, string exception) => WriteEvent(5, generatorName, exception); [Event(6, Message = "Node {0} transformed", Keywords = Keywords.Correctness, Level = EventLevel.Verbose, Task = Tasks.BuildStateTable)] - internal void NodeTransform(int nodeHashCode, string name, string tableType, int previousTable, string previousTableContent, int newTable, string newTableContent, int input1, int input2) => WriteEvent(6, nodeHashCode, name, tableType, previousTable, previousTableContent, newTable, newTableContent, input1, input2); + internal unsafe void NodeTransform(int nodeHashCode, string name, string tableType, int previousTable, string previousTableContent, int newTable, string newTableContent, int input1, int input2) + { + if (IsEnabled()) + { + fixed (char* nameBytes = name) + fixed (char* tableTypeBytes = tableType) + fixed (char* previousTableContentBytes = previousTableContent) + fixed (char* newTableContentBytes = newTableContent) + { + Span data = stackalloc EventData[] + { + GetEventDataForInt32(&nodeHashCode), + GetEventDataForString(name, nameBytes), + GetEventDataForString(tableType, tableTypeBytes), + GetEventDataForInt32(&previousTable), + GetEventDataForString(previousTableContent, previousTableContentBytes), + GetEventDataForInt32(&newTable), + GetEventDataForString(newTableContent, newTableContentBytes), + GetEventDataForInt32(&input1), + GetEventDataForInt32(&input2), + }; + + fixed (EventSource.EventData* dataPtr = data) + { + WriteEventCore(eventId: 6, data.Length, dataPtr); + } + } + } + } + + private static unsafe EventData GetEventDataForString(string value, char* ptr) + { + fixed (char* ptr2 = value) + { + if (ptr2 != ptr) + throw new ArgumentException("Pinned value must match string."); + } + + return new EventData() + { + DataPointer = (IntPtr)ptr, + Size = (value.Length + 1) * sizeof(char), + }; + } + + private static unsafe EventData GetEventDataForInt32(int* ptr) + { + return new EventData() + { + DataPointer = (IntPtr)ptr, + Size = sizeof(int), + }; + } + + private static unsafe EventData GetEventDataForInt64(long* ptr) + { + return new EventData() + { + DataPointer = (IntPtr)ptr, + Size = sizeof(long), + }; + } } } diff --git a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs index 2d518e4c11205..3da802ad40fb9 100644 --- a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs @@ -276,6 +276,26 @@ public static ImmutableArray SelectManyAsArray(this Imm 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. /// @@ -288,17 +308,37 @@ public static ImmutableArray SelectManyAsArray(this Imm 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(); @@ -955,7 +995,13 @@ internal static Dictionary> GetTypesFromM where TNamespaceOrTypeSymbol : class where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol { - var dictionary = new Dictionary>(comparer); + // 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 (name, members) in map) { diff --git a/src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs b/src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs index b310f906f72cd..3817da8a8c5a9 100644 --- a/src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs +++ b/src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs @@ -383,12 +383,12 @@ private static bool TryCompileChoice( if (lastChar == ',') { // Another option - sb.Append("|"); + sb.Append('|'); } else if (lastChar == '}') { // Close out the capture group - sb.Append(")"); + sb.Append(')'); return true; } else diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalysisContextInfo.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalysisContextInfo.cs index 823a950bb9de1..46d070ea7e920 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalysisContextInfo.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalysisContextInfo.cs @@ -128,7 +128,7 @@ private string GetFlattenedNodeText(SyntaxNode node) { if (token.Span.Start - lastEnd > 0) { - sb.Append(" "); + sb.Append(' '); } sb.Append(token.ToString()); diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerImageReference.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerImageReference.cs index e1719ca7b4594..fb75bf02d19b4 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerImageReference.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerImageReference.cs @@ -77,14 +77,14 @@ private string GetDebuggerDisplay() { sb.Append(" Path='"); sb.Append(_fullPath); - sb.Append("'"); + sb.Append('\''); } if (_display != null) { sb.Append(" Display='"); sb.Append(_display); - sb.Append("'"); + sb.Append('\''); } return sb.ToString(); diff --git a/src/Compilers/Core/Portable/DocumentationCommentId.cs b/src/Compilers/Core/Portable/DocumentationCommentId.cs index 7a31b57aeb2e4..e9efd222012e4 100644 --- a/src/Compilers/Core/Portable/DocumentationCommentId.cs +++ b/src/Compilers/Core/Portable/DocumentationCommentId.cs @@ -419,7 +419,7 @@ public override bool VisitEvent(IEventSymbol symbol) { if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); } _builder.Append(EncodeName(symbol.Name)); @@ -430,7 +430,7 @@ public override bool VisitField(IFieldSymbol symbol) { if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); } _builder.Append(EncodeName(symbol.Name)); @@ -441,7 +441,7 @@ public override bool VisitProperty(IPropertySymbol symbol) { if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); } var name = EncodePropertyName(symbol.Name); @@ -456,7 +456,7 @@ public override bool VisitMethod(IMethodSymbol symbol) { if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); _builder.Append(EncodeName(symbol.Name)); } @@ -470,7 +470,7 @@ public override bool VisitMethod(IMethodSymbol symbol) if (!symbol.ReturnsVoid) { - _builder.Append("~"); + _builder.Append('~'); this.GetReferenceGenerator(symbol).Visit(symbol.ReturnType); } @@ -481,24 +481,24 @@ private void AppendParameters(ImmutableArray parameters) { if (parameters.Length > 0) { - _builder.Append("("); + _builder.Append('('); for (int i = 0, n = parameters.Length; i < n; i++) { if (i > 0) { - _builder.Append(","); + _builder.Append(','); } var p = parameters[i]; this.GetReferenceGenerator(p.ContainingSymbol).Visit(p.Type); if (p.RefKind != RefKind.None) { - _builder.Append("@"); + _builder.Append('@'); } } - _builder.Append(")"); + _builder.Append(')'); } } @@ -511,7 +511,7 @@ public override bool VisitNamespace(INamespaceSymbol symbol) if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); } _builder.Append(EncodeName(symbol.Name)); @@ -522,14 +522,14 @@ public override bool VisitNamedType(INamedTypeSymbol symbol) { if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); } _builder.Append(EncodeName(symbol.Name)); if (symbol.TypeParameters.Length > 0) { - _builder.Append("`"); + _builder.Append('`'); _builder.Append(symbol.TypeParameters.Length); } @@ -558,7 +558,7 @@ private void BuildDottedName(ISymbol symbol) { if (this.Visit(symbol.ContainingSymbol)) { - _builder.Append("."); + _builder.Append('.'); } _builder.Append(EncodeName(symbol.Name)); @@ -588,24 +588,24 @@ public override bool VisitNamedType(INamedTypeSymbol symbol) { if (symbol.OriginalDefinition == symbol) { - _builder.Append("`"); + _builder.Append('`'); _builder.Append(symbol.TypeParameters.Length); } else if (symbol.TypeArguments.Length > 0) { - _builder.Append("{"); + _builder.Append('{'); for (int i = 0, n = symbol.TypeArguments.Length; i < n; i++) { if (i > 0) { - _builder.Append(","); + _builder.Append(','); } this.Visit(symbol.TypeArguments[i]); } - _builder.Append("}"); + _builder.Append('}'); } } @@ -623,7 +623,7 @@ public override bool VisitArrayType(IArrayTypeSymbol symbol) { this.Visit(symbol.ElementType); - _builder.Append("["); + _builder.Append('['); for (int i = 0, n = symbol.Rank; i < n; i++) { @@ -631,11 +631,11 @@ public override bool VisitArrayType(IArrayTypeSymbol symbol) if (i > 0) { - _builder.Append(","); + _builder.Append(','); } } - _builder.Append("]"); + _builder.Append(']'); return true; } @@ -643,7 +643,7 @@ public override bool VisitArrayType(IArrayTypeSymbol symbol) public override bool VisitPointerType(IPointerTypeSymbol symbol) { this.Visit(symbol.PointedAtType); - _builder.Append("*"); + _builder.Append('*'); return true; } @@ -659,7 +659,7 @@ public override bool VisitTypeParameter(ITypeParameterSymbol symbol) declarer.Visit(symbol.ContainingSymbol); Debug.Assert(!declarer.Failed); - _builder.Append(":"); + _builder.Append(':'); } if (symbol.DeclaringMethod != null) @@ -672,7 +672,7 @@ public override bool VisitTypeParameter(ITypeParameterSymbol symbol) // get count of all type parameter preceding the declaration of the type parameters containing symbol. var container = symbol.ContainingSymbol?.ContainingSymbol; var b = GetTotalTypeParameterCount(container as INamedTypeSymbol); - _builder.Append("`"); + _builder.Append('`'); _builder.Append(b + symbol.Ordinal); } diff --git a/src/Compilers/Core/Portable/Emit/AnonymousTypeKey.cs b/src/Compilers/Core/Portable/Emit/AnonymousTypeKey.cs index c862903532865..492e2dc3e76c3 100644 --- a/src/Compilers/Core/Portable/Emit/AnonymousTypeKey.cs +++ b/src/Compilers/Core/Portable/Emit/AnonymousTypeKey.cs @@ -94,7 +94,7 @@ private string GetDebuggerDisplay() { if (i > 0) { - builder.Append("|"); + builder.Append('|'); } builder.Append(this.Fields[i].Name); } diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs index 79a240adfeadc..cf862bfad8c99 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeletedMethodBody.cs @@ -12,6 +12,8 @@ namespace Microsoft.CodeAnalysis.Emit.EditAndContinue { internal sealed class DeletedMethodBody(IDeletedMethodDefinition methodDef, ImmutableArray il) : Cci.IMethodBody { + private readonly IDeletedMethodDefinition _methodDef = methodDef; + public ImmutableArray IL { get; } = il; #nullable disable @@ -24,7 +26,7 @@ internal sealed class DeletedMethodBody(IDeletedMethodDefinition methodDef, Immu public ImmutableArray LocalVariables => ImmutableArray.Empty; - public Cci.IMethodDefinition MethodDefinition => methodDef; + public Cci.IMethodDefinition MethodDefinition => _methodDef; public StateMachineMoveNextBodyDebugInfo MoveNextBodyInfo => null; diff --git a/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs b/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs index bb440b09fc71b..0bb333eea6559 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs @@ -153,7 +153,7 @@ public override string ToString() any = true; } - result.Append("]"); + result.Append(']'); return result.ToString(); } } diff --git a/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs b/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs index 10c7ac2543e5f..c11d0563495e5 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs @@ -237,8 +237,10 @@ public bool MoveNext() private sealed class DebuggerProxy(OneOrMany instance) { + private readonly OneOrMany _instance = instance; + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public T[] Items => instance.ToArray(); + public T[] Items => _instance.ToArray(); } private string GetDebuggerDisplay() diff --git a/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs b/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs index 9ecff6add2314..7f42ad11929fc 100644 --- a/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs +++ b/src/Compilers/Core/Portable/MetadataReference/AssemblyIdentity.DisplayName.cs @@ -81,11 +81,11 @@ private string BuildDisplayName(bool fullKey) sb.Append(", Version="); sb.Append(_version.Major); - sb.Append("."); + sb.Append('.'); sb.Append(_version.Minor); - sb.Append("."); + sb.Append('.'); sb.Append(_version.Build); - sb.Append("."); + sb.Append('.'); sb.Append(_version.Revision); sb.Append(", Culture="); @@ -848,15 +848,15 @@ private static bool Unescape(StringBuilder sb, string str, ref int i) return true; case 't': - sb.Append("\t"); + sb.Append('\t'); return true; case 'n': - sb.Append("\n"); + sb.Append('\n'); return true; case 'r': - sb.Append("\r"); + sb.Append('\r'); return true; case 'u': diff --git a/src/Compilers/Core/Portable/MetadataReference/MetadataImageReference.cs b/src/Compilers/Core/Portable/MetadataReference/MetadataImageReference.cs index bffbe9af554d9..624d34c0174a8 100644 --- a/src/Compilers/Core/Portable/MetadataReference/MetadataImageReference.cs +++ b/src/Compilers/Core/Portable/MetadataReference/MetadataImageReference.cs @@ -62,7 +62,7 @@ private string GetDebuggerDisplay() { sb.Append(" Aliases={"); sb.Append(string.Join(", ", Properties.Aliases)); - sb.Append("}"); + sb.Append('}'); } if (Properties.EmbedInteropTypes) @@ -74,14 +74,14 @@ private string GetDebuggerDisplay() { sb.Append(" Path='"); sb.Append(FilePath); - sb.Append("'"); + sb.Append('\''); } if (_display != null) { sb.Append(" Display='"); sb.Append(_display); - sb.Append("'"); + sb.Append('\''); } return sb.ToString(); diff --git a/src/Compilers/Core/Portable/Syntax/GreenNode.NodeEnumerable.cs b/src/Compilers/Core/Portable/Syntax/GreenNode.NodeEnumerable.cs index c49e0685420fb..93098add0fbdb 100644 --- a/src/Compilers/Core/Portable/Syntax/GreenNode.NodeEnumerable.cs +++ b/src/Compilers/Core/Portable/Syntax/GreenNode.NodeEnumerable.cs @@ -13,8 +13,10 @@ internal abstract partial class GreenNode [NonCopyable] public ref struct NodeEnumerable(GreenNode node) { + private readonly GreenNode _node = node; + public readonly Enumerator GetEnumerator() - => new Enumerator(node); + => new Enumerator(_node); [NonCopyable] public ref struct Enumerator diff --git a/src/Compilers/Core/Portable/Syntax/LineMapping.cs b/src/Compilers/Core/Portable/Syntax/LineMapping.cs index a481c4dc45bcf..a79c126248eed 100644 --- a/src/Compilers/Core/Portable/Syntax/LineMapping.cs +++ b/src/Compilers/Core/Portable/Syntax/LineMapping.cs @@ -65,7 +65,7 @@ public override int GetHashCode() builder.Append(Span); if (CharacterOffset.HasValue) { - builder.Append(","); + builder.Append(','); builder.Append(CharacterOffset.GetValueOrDefault()); } builder.Append(" -> "); diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf index 34592a071173b..0106a258cfa33 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.cs.xlf @@ -225,7 +225,7 @@ The temporary path for legacy file signing is unavailable. - Dočasná cesta pro starší verzi podepisování souborů není k dispozici. + Dočasná cesta pro podepisování starší verze souboru není k dispozici. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf index b3f47813c9c2b..8f06782d9f1ae 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.ja.xlf @@ -225,7 +225,7 @@ The temporary path for legacy file signing is unavailable. - レガシ ファイル署名の一時パスは使用できません。 + レガシ ファイル署名用の一時パスは使用できません。 diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf index 6390e250a58d2..ab8fa9d2378b8 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.pt-BR.xlf @@ -225,7 +225,7 @@ The temporary path for legacy file signing is unavailable. - O caminho temporário para assinatura de arquivo herdado não está disponível. + O caminho temporário para assinatura de arquivos herdados não está disponível. diff --git a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf index 54f856d6d4573..7997103691f46 100644 --- a/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf +++ b/src/Compilers/Core/Portable/xlf/CodeAnalysisResources.zh-Hant.xlf @@ -225,7 +225,7 @@ The temporary path for legacy file signing is unavailable. - 舊版檔案簽章的暫存路徑無法使用。 + 舊版檔案簽署的暫存路徑無法使用。 diff --git a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs index 59c078def46fb..8384b3c4572bc 100644 --- a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs +++ b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs @@ -220,7 +220,7 @@ private static void GetFlowGraph(System.Text.StringBuilder stringBuilder, Compil stringBuilder.Append("*2"); } - stringBuilder.Append("]"); + stringBuilder.Append(']'); } stringBuilder.AppendLine(); diff --git a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs index 0d6b39919f139..5a17d6ac9d980 100644 --- a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs +++ b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs @@ -638,7 +638,7 @@ private void LogLoopStatementHeader(ILoopOperation operation, bool? isChecked = { propertyStringBuilder.Append($", Checked"); } - propertyStringBuilder.Append(")"); + propertyStringBuilder.Append(')'); LogString(propertyStringBuilder.ToString()); LogCommonPropertiesAndNewLine(operation); diff --git a/src/Compilers/Test/Core/Diagnostics/DiagnosticDescription.cs b/src/Compilers/Test/Core/Diagnostics/DiagnosticDescription.cs index fd94fad8c30af..01817d73a198a 100644 --- a/src/Compilers/Test/Core/Diagnostics/DiagnosticDescription.cs +++ b/src/Compilers/Test/Core/Diagnostics/DiagnosticDescription.cs @@ -382,12 +382,12 @@ public override string ToString() sb.Append("Diagnostic("); if (_errorCodeType == typeof(string)) { - sb.Append("\"").Append(_code).Append("\""); + sb.Append('"').Append(_code).Append('"'); } else { sb.Append(_errorCodeType.Name); - sb.Append("."); + sb.Append('.'); sb.Append(Enum.GetName(_errorCodeType, _code)); } @@ -412,7 +412,7 @@ public override string ToString() sb.Append(", isSuppressed: true"); } - sb.Append(")"); + sb.Append(')'); if (_arguments != null) { @@ -426,7 +426,7 @@ public override string ToString() sb.Append(", "); } } - sb.Append(")"); + sb.Append(')'); } if (_startPosition != null) @@ -435,7 +435,7 @@ public override string ToString() sb.Append(_startPosition.Value.Line + 1); sb.Append(", "); sb.Append(_startPosition.Value.Character + 1); - sb.Append(")"); + sb.Append(')'); } if (_isWarningAsError) diff --git a/src/Compilers/Test/Core/Mocks/TestEqualityComparer.cs b/src/Compilers/Test/Core/Mocks/TestEqualityComparer.cs index 94c8ab87c1037..a022dd39011d0 100644 --- a/src/Compilers/Test/Core/Mocks/TestEqualityComparer.cs +++ b/src/Compilers/Test/Core/Mocks/TestEqualityComparer.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +#pragma warning disable RS0062 // Do not implicitly capture primary constructor parameters + namespace Roslyn.Test.Utilities { public class TestEqualityComparer(Func? equals = null, Func? getHashCode = null) : IEqualityComparer diff --git a/src/Compilers/Test/Core/Platform/Custom/MetadataSignatureHelper.cs b/src/Compilers/Test/Core/Platform/Custom/MetadataSignatureHelper.cs index bcae71cd3f2c4..a0a0820eb9cbe 100644 --- a/src/Compilers/Test/Core/Platform/Custom/MetadataSignatureHelper.cs +++ b/src/Compilers/Test/Core/Platform/Custom/MetadataSignatureHelper.cs @@ -53,7 +53,7 @@ private static void AppendType(Type type, StringBuilder sb, bool showGenericCons var genericConstraints = typeInfo.GetGenericParameterConstraints(); if (genericConstraints.Length > 0) { - sb.Append("("); + sb.Append('('); foreach (var genericConstraint in genericConstraints) { AppendType(genericConstraint, sb); @@ -88,9 +88,9 @@ private static void AppendValue(object value, StringBuilder sb, bool includeAssi private static void AppendCustomAttributeData(CustomAttributeData attribute, StringBuilder sb) { - sb.Append("["); + sb.Append('['); AppendType(attribute.Constructor.DeclaringType, sb); - sb.Append("("); + sb.Append('('); foreach (var positionalArgument in attribute.ConstructorArguments) { AppendValue(positionalArgument.Value, sb, false); @@ -117,7 +117,7 @@ private static void AppendParameterInfo(ParameterInfo parameter, StringBuilder s attribute.AttributeType != typeof(MarshalAsAttribute)) { AppendCustomAttributeData(attribute, sb); - sb.Append(" "); + sb.Append(' '); } } @@ -138,13 +138,13 @@ private static void AppendParameterInfo(ParameterInfo parameter, StringBuilder s AppendParameterAttributes(sb, parameter.Attributes, all: false); if (sb.Length > length) { - sb.Append(" "); + sb.Append(' '); } AppendType(parameter.ParameterType, sb); if (!string.IsNullOrWhiteSpace(parameter.Name)) // If this is not the 'return' parameter { - sb.Append(" "); + sb.Append(' '); sb.Append(parameter.Name); var defaultValue = parameter.RawDefaultValue; @@ -322,7 +322,7 @@ public static StringBuilder AppendMethodImplAttributes(StringBuilder sb, MethodI } sb.Append(codeType); - sb.Append(" "); + sb.Append(' '); sb.Append((attributes & MethodImplAttributes.Unmanaged) == MethodImplAttributes.Unmanaged ? "unmanaged" : "managed"); if ((attributes & MethodImplAttributes.PreserveSig) != 0) @@ -391,9 +391,9 @@ public static StringBuilder AppendTypeAttributes(StringBuilder sb, TypeAttribute if ((attributes & TypeAttributes.Abstract) != 0) sb.Append(" abstract"); - sb.Append(" "); + sb.Append(' '); sb.Append(layout); - sb.Append(" "); + sb.Append(' '); sb.Append(stringFormat); if ((attributes & TypeAttributes.Import) != 0) @@ -420,30 +420,30 @@ private static void AppendMethodInfo(MethodInfo method, StringBuilder sb) foreach (var attribute in method.CustomAttributes) { - sb.Append(" "); + sb.Append(' '); AppendCustomAttributeData(attribute, sb); } - sb.Append(" "); + sb.Append(' '); AppendMethodAttributes(sb, method.Attributes); - sb.Append(" "); + sb.Append(' '); AppendParameterInfo(method.ReturnParameter, sb); - sb.Append(" "); + sb.Append(' '); sb.Append(method.Name); if (method.IsGenericMethod) { - sb.Append("<"); + sb.Append('<'); foreach (var typeParameter in method.GetGenericArguments()) { AppendType(typeParameter, sb, true); AppendComma(sb); } RemoveTrailingComma(sb); - sb.Append(">"); + sb.Append('>'); } - sb.Append("("); + sb.Append('('); foreach (var parameter in method.GetParameters()) { AppendParameterInfo(parameter, sb); @@ -460,36 +460,36 @@ private static void AppendConstructorInfo(ConstructorInfo constructor, StringBui foreach (var attribute in constructor.CustomAttributes) { - sb.Append(" "); + sb.Append(' '); AppendCustomAttributeData(attribute, sb); } - sb.Append(" "); + sb.Append(' '); AppendMethodAttributes(sb, constructor.Attributes); - sb.Append(" "); + sb.Append(' '); sb.Append("void "); sb.Append(constructor.Name); if (constructor.IsGenericMethod) { - sb.Append("<"); + sb.Append('<'); foreach (var typeParameter in constructor.GetGenericArguments()) { AppendType(typeParameter, sb, true); AppendComma(sb); } RemoveTrailingComma(sb); - sb.Append(">"); + sb.Append('>'); } - sb.Append("("); + sb.Append('('); foreach (var parameter in constructor.GetParameters()) { AppendParameterInfo(parameter, sb); AppendComma(sb); } RemoveTrailingComma(sb); - sb.Append(")"); + sb.Append(')'); var implFlags = constructor.GetMethodImplementationFlags(); if (implFlags.HasFlag(MethodImplAttributes.IL)) @@ -525,7 +525,7 @@ private static void AppendPropertyInfo(PropertyInfo property, StringBuilder sb) foreach (var attribute in property.CustomAttributes) { AppendCustomAttributeData(attribute, sb); - sb.Append(" "); + sb.Append(' '); } foreach (var modreq in property.GetRequiredCustomModifiers()) { @@ -564,20 +564,20 @@ private static void AppendPropertyInfo(PropertyInfo property, StringBuilder sb) sb.Append(propertyAccessors[0].IsStatic ? "static " : "instance "); } AppendType(property.PropertyType, sb); - sb.Append(" "); + sb.Append(' '); sb.Append(property.Name); var indexParameters = property.GetIndexParameters(); if (indexParameters.Length > 0) { - sb.Append("("); + sb.Append('('); foreach (var indexParameter in indexParameters) { AppendParameterInfo(indexParameter, sb); AppendComma(sb); } RemoveTrailingComma(sb); - sb.Append(")"); + sb.Append(')'); } } @@ -588,7 +588,7 @@ private static void AppendFieldInfo(FieldInfo field, StringBuilder sb) foreach (var attribute in field.CustomAttributes) { AppendCustomAttributeData(attribute, sb); - sb.Append(" "); + sb.Append(' '); } foreach (var modreq in field.GetRequiredCustomModifiers()) @@ -632,7 +632,7 @@ private static void AppendFieldInfo(FieldInfo field, StringBuilder sb) sb.Append(field.IsStatic ? "static " : "instance "); AppendType(field.FieldType, sb); - sb.Append(" "); + sb.Append(' '); sb.Append(field.Name); if (field.IsLiteral) @@ -648,7 +648,7 @@ private static void AppendEventInfo(EventInfo @event, StringBuilder sb) foreach (var attribute in @event.CustomAttributes) { AppendCustomAttributeData(attribute, sb); - sb.Append(" "); + sb.Append(' '); } if (@event.Attributes.HasFlag(EventAttributes.SpecialName)) @@ -657,7 +657,7 @@ private static void AppendEventInfo(EventInfo @event, StringBuilder sb) sb.Append("rtspecialname "); AppendType(@event.EventHandlerType, sb); - sb.Append(" "); + sb.Append(' '); sb.Append(@event.Name); } #endregion diff --git a/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs b/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs index 8eb3d47abd37e..85b970563e656 100644 --- a/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs +++ b/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs @@ -77,6 +77,7 @@ public SingleFileTestGenerator2(string content, string hintName = "generatedFile } } +#pragma warning disable RS0062 // Do not implicitly capture primary constructor paramters internal class CallbackGenerator( Action onInit, Action onExecute, @@ -113,6 +114,7 @@ public void Execute(GeneratorExecutionContext context) } } } +#pragma warning restore RS0062 // Do not implicitly capture primary constructor paramters internal class CallbackGenerator2 : CallbackGenerator { diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf index ff0ecc33800d2..14ac130b36227 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.cs.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + Argument diagnosticId atributu Experimental musí být platný identifikátor diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf index 44ed8139728ee..ca0b81844f1dd 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.fr.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + L’argument diagnosticId de l’attribut « Experimental » doit être un identificateur valide diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf index 4aacd8a070373..d5842e214f829 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.ja.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + 'Experimental' 属性への diagnosticId 引数は有効な識別子である必要があります diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf index 21262d9af44a5..fd7c3102370c0 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pl.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + Argument diagnosticId atrybutu „Experimental” musi być prawidłowym identyfikatorem diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf index 134d2cbc8c775..46759bf7c9895 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.pt-BR.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + O argumento diagnosticId para o atributo 'Experimental' deve ser um identificador válido diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf index e99fd1142bc4f..2697ba04404ef 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.tr.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + 'Experimental' özniteliğinin diagnosticId bağımsız değişkeni geçerli bir tanımlayıcı olmalıdır diff --git a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf index 1991dff7e22d3..d807f96ff7314 100644 --- a/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf +++ b/src/Compilers/VisualBasic/Portable/xlf/VBResources.zh-Hant.xlf @@ -44,7 +44,7 @@ The diagnosticId argument to the 'Experimental' attribute must be a valid identifier - The diagnosticId argument to the 'Experimental' attribute must be a valid identifier + 'Experimental' 屬性的 diagnosticId 引數必須是有效的識別碼 diff --git a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs index 9332cdfbb143e..aa6ffca873414 100644 --- a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs +++ b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs @@ -566,7 +566,7 @@ private static bool ShouldAddBraceForAccessorDeclaration(AccessorDeclarationSynt && parentOfParent is PropertyDeclarationSyntax) { var otherAccessors = accessorListNode.Accessors - .Except(new[] { accessorDeclarationNode }) + .Except([accessorDeclarationNode]) .ToImmutableArray(); if (!otherAccessors.IsEmpty) { diff --git a/src/EditorFeatures/CSharp/CompleteStatement/CompleteStatementCommandHandler.cs b/src/EditorFeatures/CSharp/CompleteStatement/CompleteStatementCommandHandler.cs index 5e2f2f42841bb..e6ea5cad03fc8 100644 --- a/src/EditorFeatures/CSharp/CompleteStatement/CompleteStatementCommandHandler.cs +++ b/src/EditorFeatures/CSharp/CompleteStatement/CompleteStatementCommandHandler.cs @@ -147,7 +147,7 @@ private static bool TryGetStartingNode( var token = root.FindTokenOnLeftOfPosition(caretPosition); if (token.SyntaxTree == null - || token.SyntaxTree.IsEntirelyWithinComment(caretPosition, cancellationToken)) + || token.SyntaxTree.IsInNonUserCode(caretPosition, cancellationToken)) { return false; } diff --git a/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs b/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs index b00077eab235f..87d2286dad4dd 100644 --- a/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/AddMissingImports/CSharpAddMissingImportsRefactoringProviderTests.cs @@ -337,8 +337,7 @@ public class D { } await TestMissingInRegularAndScriptAsync(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/31768")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/31768")] public async Task AddMissingImports_AddMultipleImports_NoPreviousImports() { var code = """ diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticBraceCompletionTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticBraceCompletionTests.cs index 1be51ceffa841..ab7bf1bd81842 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticBraceCompletionTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticBraceCompletionTests.cs @@ -756,8 +756,7 @@ class C CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void Collection_Initializer_OpenBraceOnSameLine_Enter() { var code = @"using System.Collections.Generic; @@ -793,8 +792,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void Collection_Initializer_OpenBraceOnDifferentLine_Enter() { var code = @"using System.Collections.Generic; @@ -826,8 +824,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void Object_Initializer_OpenBraceOnSameLine_Enter() { var code = @"class C @@ -869,8 +866,7 @@ class Goo CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void Object_Initializer_OpenBraceOnDifferentLine_Enter() { var code = @"class C @@ -908,8 +904,7 @@ class Goo CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void ArrayImplicit_Initializer_OpenBraceOnSameLine_Enter() { var code = @"class C @@ -941,8 +936,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void ArrayImplicit_Initializer_OpenBraceOnDifferentLine_Enter() { var code = @"class C @@ -970,8 +964,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void ArrayExplicit1_Initializer_OpenBraceOnSameLine_Enter() { var code = @"class C @@ -1003,8 +996,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void ArrayExplicit1_Initializer_OpenBraceOnDifferentLine_Enter() { var code = @"class C @@ -1032,8 +1024,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void ArrayExplicit2_Initializer_OpenBraceOnSameLine_Enter() { var code = @"class C @@ -1064,8 +1055,7 @@ public void man() CheckReturn(session.Session, 12, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070773")] public void ArrayExplicit2_Initializer_OpenBraceOnDifferentLine_Enter() { var code = @"class C @@ -1094,8 +1084,7 @@ public void man() } [WorkItem("https://github.com/dotnet/roslyn/issues/3447")] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850540")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850540")] public void BlockIndentationWithAutomaticBraceFormattingDisabled() { var code = @"class C @@ -1132,8 +1121,7 @@ public void X() CheckReturn(session.Session, 4, expectedAfterReturn); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2224")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2224")] public void NoSmartOrBlockIndentationWithAutomaticBraceFormattingDisabled() { var code = @"namespace NS1 @@ -1160,8 +1148,7 @@ public class C1 Assert.Equal(expected, session.Session.SubjectBuffer.CurrentSnapshot.GetText()); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2330")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2330")] public void BlockIndentationWithAutomaticBraceFormatting() { var code = @"namespace NS1 @@ -1198,8 +1185,7 @@ public class C1 CheckReturn(session.Session, 8, expectedAfterReturn); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2330")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2330")] public void BlockIndentationWithAutomaticBraceFormattingSecondSet() { var code = @"namespace NS1 diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLessAndGreaterThanCompletionTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLessAndGreaterThanCompletionTests.cs index ca3661bd87929..ecbe91d23d2b6 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLessAndGreaterThanCompletionTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLessAndGreaterThanCompletionTests.cs @@ -174,8 +174,7 @@ void Method() CheckStart(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531637")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531637")] public void TypeParameterReturnType() { var code = """ @@ -191,8 +190,7 @@ class C CheckOverType(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531637")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531637")] public void TypeParameterInDecl() { var code = """ @@ -208,8 +206,7 @@ void List$$ CheckOverType(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531637")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531637")] public void TypeParameterInDeclWith() { var code = """ @@ -225,8 +222,7 @@ async Task$$ CheckOverType(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530864")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530864")] public void TypeArgumentWithUsing() { var code = """ @@ -247,8 +243,7 @@ void Test() CheckOverType(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530864")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530864")] public void TypeArgumentNoUsing() { var code = """ @@ -265,8 +260,7 @@ void Test() CheckStart(session.Session, expectValidSession: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/1628")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/1628")] public void NotInLessThanComparisonOperation() { var code = """ @@ -284,8 +278,7 @@ void Test(int[] args) CheckStart(session.Session, expectValidSession: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/1628")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/1628")] public void NotInLessThanComparisonOperationAfterConditionalAccessExpression() { var code = """ @@ -303,8 +296,7 @@ void Test(object[] args, object[] other) CheckStart(session.Session, expectValidSession: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/1628")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/1628")] public void TypeArgumentInConditionalAccessExpressionSimple() { var code = """ @@ -322,8 +314,7 @@ void Test(object[] args) CheckStart(session.Session); } - [WorkItem("https://github.com/dotnet/roslyn/issues/1628")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/1628")] public void TypeArgumentInConditionalAccessExpressionNested() { var code = """ @@ -354,8 +345,7 @@ public void Method() { } CheckOverType(session.Session); } - [WorkItem("https://github.com/dotnet/roslyn/issues/1628")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/1628")] public void TypeArgumentInConditionalAccessExpressionDeeplyNested() { var code = """ @@ -392,8 +382,7 @@ public void DoSomething() { } CheckStart(session.Session); } - [WorkItem("https://github.com/dotnet/roslyn/issues/1628")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/1628")] public void TypeArgumentInConditionalAccessExpressionWithLambdas() { var code = """ diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs index d9156a4a5c980..f219cb1cf673f 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs @@ -273,8 +273,7 @@ void Method() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedMethod() { Test(@"class T @@ -287,8 +286,7 @@ int M() => 1 + 2$$ }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedOperator() { Test(@"class Complex @@ -305,8 +303,7 @@ public void ExpressionBodiedOperator() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedConversionOperator() { Test(@"using System; @@ -337,8 +334,7 @@ public struct DBBool }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedProperty() { Test(@"class T @@ -351,8 +347,7 @@ public void ExpressionBodiedProperty() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedIndexer() { Test(@"using System; @@ -369,8 +364,7 @@ class SampleCollection }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedMethodWithBlockBodiedAnonymousMethodExpression() { Test(@"using System; @@ -391,8 +385,7 @@ Func Y() => delegate (int x) }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedMethodWithSingleLineBlockBodiedAnonymousMethodExpression() { Test(@"using System; @@ -407,8 +400,7 @@ class TestClass }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedMethodWithBlockBodiedSimpleLambdaExpression() { Test(@"using System; @@ -429,8 +421,7 @@ Func Y() => f => }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedMethodWithExpressionBodiedSimpleLambdaExpression() { Test(@"using System; @@ -445,8 +436,7 @@ Func Y() => f => f * 9$$ }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void ExpressionBodiedMethodWithBlockBodiedAnonymousMethodExpressionInMethodArgs() { Test(@"using System; @@ -471,8 +461,7 @@ class TestClass }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void Format_SimpleExpressionBodiedMember() { Test(@"class T @@ -485,8 +474,7 @@ int M() => 1 + 2$$ }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void Format_ExpressionBodiedMemberWithSingleLineBlock() { Test(@"using System; @@ -501,8 +489,7 @@ class TestClass }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/3944")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/3944")] public void Format_ExpressionBodiedMemberWithMultiLineBlock() { Test(@"using System; @@ -622,8 +609,7 @@ object goo(object o) }", completionActive: true); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530352")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530352")] public void EmbededStatement3() { Test(@"class Program @@ -644,8 +630,7 @@ void Method() }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530716")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530716")] public void DoNotAssertOnMultilineToken() { Test(@"interface I @@ -658,8 +643,7 @@ void M(string s = @""""""$$ }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530718")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530718")] public void AutomaticLineFormat() { Test(@"class C @@ -743,8 +727,7 @@ public void NotAfterAutoPropertyDeclaration() }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void DelegatedInEmptyBlock() { Test(@"class TestClass @@ -762,8 +745,7 @@ void Method() }", assertNextHandlerInvoked: true); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void DelegatedInEmptyBlock2() { Test(@"class TestClass @@ -781,8 +763,7 @@ void Method() }", assertNextHandlerInvoked: true); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void NotDelegatedOutsideEmptyBlock() { Test(@"class TestClass @@ -801,8 +782,7 @@ void Method() }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void NotDelegatedAfterOpenBraceAndMissingCloseBrace() { Test(@"class TestClass @@ -821,8 +801,7 @@ void Method() }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void NotDelegatedInNonEmptyBlock() { Test(@"class TestClass @@ -841,8 +820,7 @@ void Method() }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void NotDelegatedAfterOpenBraceInAnonymousObjectCreationExpression() { Test(@"class TestClass @@ -861,8 +839,7 @@ void Method() }"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/150480")] public void NotDelegatedAfterOpenBraceObjectCreationExpression() { Test(@"class TestClass diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs index fe40fcfbb024e..bda3d46fe1874 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLiteralCompletionTests.cs @@ -451,8 +451,7 @@ void Method() CheckBackspace(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546047")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546047")] public void VerbatimStringDoubleQuote() { var code = """ diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticParenthesisCompletionTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticParenthesisCompletionTests.cs index 66a1a8de104f3..226a300a88580 100644 --- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticParenthesisCompletionTests.cs +++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticParenthesisCompletionTests.cs @@ -174,8 +174,7 @@ int Method(int i) CheckStart(session.Session); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546337")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546337")] public void OpenParenthesisWithExistingCloseParen() { var code = """ diff --git a/src/EditorFeatures/CSharpTest/BlockCommentEditing/BlockCommentEditingTests.cs b/src/EditorFeatures/CSharpTest/BlockCommentEditing/BlockCommentEditingTests.cs index 0e769f39959a7..199d5fbe40ce7 100644 --- a/src/EditorFeatures/CSharpTest/BlockCommentEditing/BlockCommentEditingTests.cs +++ b/src/EditorFeatures/CSharpTest/BlockCommentEditing/BlockCommentEditingTests.cs @@ -20,8 +20,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.BlockCommentEditing [Trait(Traits.Feature, Traits.Features.BlockCommentEditing)] public class BlockCommentEditingTests : AbstractTypingCommandHandlerTest { - [WorkItem("https://github.com/dotnet/roslyn/issues/11057")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/11057")] public void EdgeCase0() { var code = @" @@ -34,8 +33,7 @@ public void EdgeCase0() Verify(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/11057")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/11057")] public void EdgeCase1() { var code = @" @@ -48,8 +46,7 @@ public void EdgeCase1() Verify(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/11056")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/11056")] public void EdgeCase2() { var code = @" @@ -62,8 +59,7 @@ public void EdgeCase2() Verify(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/11056")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/11056")] public void EdgeCase3() { var code = @" @@ -76,8 +72,7 @@ public void EdgeCase3() Verify(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/16128")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/16128")] public void EofCase0() { var code = @" @@ -88,8 +83,7 @@ public void EofCase0() Verify(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/16128")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/16128")] public void EofCase1() { var code = @" @@ -100,8 +94,7 @@ public void EofCase1() Verify(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/16128")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/16128")] public void EofCase2() { var code = @" diff --git a/src/EditorFeatures/CSharpTest/BraceMatching/CSharpBraceMatcherTests.cs b/src/EditorFeatures/CSharpTest/BraceMatching/CSharpBraceMatcherTests.cs index 3506055ac5774..7822776f4e951 100644 --- a/src/EditorFeatures/CSharpTest/BraceMatching/CSharpBraceMatcherTests.cs +++ b/src/EditorFeatures/CSharpTest/BraceMatching/CSharpBraceMatcherTests.cs @@ -621,8 +621,7 @@ public async Task TestVerbatimUtf8String7() await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestConditionalDirectiveWithSingleMatchingDirective() { var code = """ @@ -643,8 +642,7 @@ public class C await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestConditionalDirectiveWithTwoMatchingDirectives() { var code = """ @@ -667,8 +665,7 @@ public class C await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestConditionalDirectiveWithAllMatchingDirectives() { var code = """ @@ -693,8 +690,7 @@ public class C await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestRegionDirective() { var code = """ @@ -715,8 +711,7 @@ public class C await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestInterleavedDirectivesInner() { var code = """ @@ -755,8 +750,7 @@ void Test() await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestInterleavedDirectivesOuter() { var code = """ @@ -795,8 +789,7 @@ void Test() await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestUnmatchedDirective1() { var code = """ @@ -815,8 +808,7 @@ public class C await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7120")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")] public async Task TestUnmatchedDirective2() { var code = """ @@ -835,8 +827,7 @@ public class C await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7534")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7534")] public async Task TestUnmatchedConditionalDirective() { var code = """ @@ -861,8 +852,7 @@ static void Main(string[] args) await TestAsync(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7534")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7534")] public async Task TestUnmatchedConditionalDirective2() { var code = """ diff --git a/src/EditorFeatures/CSharpTest/ChangeSignature/AddParameterTests.OptionalParameter.SymbolKinds.cs b/src/EditorFeatures/CSharpTest/ChangeSignature/AddParameterTests.OptionalParameter.SymbolKinds.cs index f431ba64cd03e..f12de90c83934 100644 --- a/src/EditorFeatures/CSharpTest/ChangeSignature/AddParameterTests.OptionalParameter.SymbolKinds.cs +++ b/src/EditorFeatures/CSharpTest/ChangeSignature/AddParameterTests.OptionalParameter.SymbolKinds.cs @@ -59,8 +59,7 @@ public D() : base(1, 100, z: 102) { } await TestChangeSignatureViaCommandAsync(LanguageNames.CSharp, markup, updatedSignature: updatedSignature, expectedUpdatedInvocationDocumentCode: updatedCode); } - [WorkItem("https://github.com/dotnet/roslyn/issues/44126")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/44126")] public async Task AddOptionalParameter_ToConstructor_ImplicitObjectCreation() { var markup = """ diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticTaggerTests.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticTaggerTests.cs index 73a9d951de834..5007f46d0d7dc 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticTaggerTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticTaggerTests.cs @@ -26,8 +26,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification [Trait(Traits.Feature, Traits.Features.Classification)] public class SyntacticTaggerTests { - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1032665")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1032665")] public async Task TestTagsChangedForPortionThatChanged() { var code = @@ -88,8 +87,7 @@ class Program2 Assert.Equal(2, callstacks.Count); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1032665")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1032665")] public async Task TestTagsChangedAfterDelete() { var code = diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs index bac72b2beb2c2..c3121d826706d 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests.cs @@ -1176,8 +1176,7 @@ internal class C index: 1); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538516")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538516")] public async Task TestGenerateClassFromIntoNewNamespace() { await TestAddDocumentInRegularAndScriptAsync( @@ -3356,8 +3355,7 @@ internal class @int index: 1); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539535")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539535")] public async Task TestGenerateIntoNewFile() { await TestAddDocumentInRegularAndScriptAsync( @@ -4684,8 +4682,7 @@ await TestSmartTagTextAsync( string.Format(FeaturesResources.Generate_0_1_in_new_file, "class", "Goo")); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543853")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543853")] public async Task TestAddDocumentForGlobalNamespace() { await TestAddDocumentInRegularAndScriptAsync( @@ -4857,8 +4854,7 @@ public class C await TestInRegularAndScriptAsync(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/932602")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/932602")] public async Task TestGenerateTypeInFolderNotDefaultNamespace_0() { var code = @" @@ -4917,8 +4913,7 @@ await TestAddDocumentInRegularAndScriptAsync(code, options: Option(CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped, NotificationOption2.Silent))); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/932602")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/932602")] public async Task TestGenerateTypeInFolderNotDefaultNamespace_1() { var code = @" @@ -5308,8 +5303,7 @@ public B() index: 2); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17361")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17361")] public async Task TestPreserveFileBanner1() { await TestAddDocumentInRegularAndScriptAsync( @@ -5331,8 +5325,7 @@ internal class Goo expectedDocumentName: "Goo.cs"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17361")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17361")] public async Task TestPreserveFileBanner2() { await TestAddDocumentInRegularAndScriptAsync( @@ -5351,8 +5344,7 @@ void Main ( ) expectedDocumentName: "Goo.cs"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17361")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17361")] public async Task TestPreserveFileBanner3() { await TestAddDocumentInRegularAndScriptAsync( @@ -5382,8 +5374,7 @@ public Goo(StackOverflowException e) expectedDocumentName: "Goo.cs"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17361")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17361")] public async Task TestPreserveFileBanner4() { await TestAddDocumentInRegularAndScriptAsync( diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs index 25675f21490e0..09c26fad47eb2 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs @@ -762,8 +762,7 @@ public interface Goo newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateType_UsingsNotNeeded_InNewFile_InFolder() { await TestWithMockedGenerateTypeDialog( @@ -802,8 +801,7 @@ public interface Goo newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateType_UsingsNeeded_InNewFile_InFolder() { await TestWithMockedGenerateTypeDialog( @@ -845,8 +843,7 @@ void Main() newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateType_UsingsNotNeeded_InNewFile_InFolder_NotSimpleName() { await TestWithMockedGenerateTypeDialog( @@ -882,8 +879,7 @@ public interface Goo newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateType_UsingsNeeded_InNewFile_InFolder_DefaultNamespace() { await TestWithMockedGenerateTypeDialog( @@ -926,8 +922,7 @@ void Main() newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateType_UsingsNotNeeded_InNewFile_InFolder_DefaultNamespace() { await TestWithMockedGenerateTypeDialog( @@ -974,8 +969,7 @@ void Main() newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateType_UsingsNotNeeded_InNewFile_InFolder_DefaultNamespace_NotSimpleName() { await TestWithMockedGenerateTypeDialog( @@ -1024,8 +1018,7 @@ namespace A.B newFileName: "Test2.cs"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/898452")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/898452")] public async Task GenerateType_InValidFolderNameNotMadeNamespace() { await TestWithMockedGenerateTypeDialog( @@ -1273,8 +1266,7 @@ public interface Goo projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoSameLanguageDifferentProjectNewFile_Folders_Usings() { await TestWithMockedGenerateTypeDialog( @@ -1319,8 +1311,7 @@ void Main() projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoSameLanguageDifferentProjectNewFile_Folders_NoUsings_NotSimpleName() { await TestWithMockedGenerateTypeDialog( @@ -1359,8 +1350,7 @@ public interface Goo projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoSameLanguageDifferentProjectNewFile_Folders_Usings_DefaultNamespace() { await TestWithMockedGenerateTypeDialog( @@ -1406,8 +1396,7 @@ void Main() projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoSameLanguageDifferentProjectNewFile_Folders_NoUsings_NotSimpleName_DefaultNamespace() { await TestWithMockedGenerateTypeDialog( @@ -1486,8 +1475,7 @@ End Namespace projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoDifferentLanguageNewFile_Folders_Usings() { await TestWithMockedGenerateTypeDialog( @@ -1531,8 +1519,7 @@ void Main() projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoDifferentLanguageNewFile_Folders_NoUsings_NotSimpleName() { await TestWithMockedGenerateTypeDialog( @@ -1570,8 +1557,7 @@ End Namespace projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoDifferentLanguageNewFile_Folders_Usings_RootNamespace() { await TestWithMockedGenerateTypeDialog( @@ -1616,8 +1602,7 @@ void Main() projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoDifferentLanguageNewFile_Folders_NoUsings_NotSimpleName_RootNamespace() { await TestWithMockedGenerateTypeDialog( @@ -1656,8 +1641,7 @@ End Namespace projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850101")] public async Task GenerateTypeIntoDifferentLanguageNewFile_Folders_NoUsings_NotSimpleName_RootNamespace_ProjectReference() { await TestWithMockedGenerateTypeDialog( @@ -1702,8 +1686,7 @@ End Namespace projectName: "Assembly2"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/858826")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/858826")] public async Task GenerateTypeIntoDifferentLanguageNewFileAdjustFileExtension() { await TestWithMockedGenerateTypeDialog( @@ -1920,8 +1903,7 @@ End Namespace } [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/861362")] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/869593")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/869593")] public async Task GenerateModuleFromCSharpToVisualBasicInTypeContext() { await TestWithMockedGenerateTypeDialog( diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/AddParameterCheckTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/AddParameterCheckTests.cs index 2f70c53fd8eb8..33ffe9790ea5f 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/AddParameterCheckTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/AddParameterCheckTests.cs @@ -1813,8 +1813,7 @@ int this[[||]string s] await VerifyCS.VerifyRefactoringAsync(code, code); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/63307")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63307")] public async Task TestNotOnIndexerParameterInRecordWithParameter() { var code = """ diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs index c9a289ffbe29c..a5ed7ad17fe5b 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs @@ -832,8 +832,7 @@ class Inner { await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/16283")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/16283")] public async Task TestLeadingTrivia1() { var code = @@ -869,8 +868,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17171")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17171")] public async Task TestInsertFinalNewLine() { var code = @@ -908,8 +906,7 @@ await TestMoveTypeToNewFileAsync( options: Option(FormattingOptions2.InsertFinalNewLine, true)); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17171")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17171")] public async Task TestInsertFinalNewLine2() { var code = @@ -946,8 +943,7 @@ await TestMoveTypeToNewFileAsync( options: Option(FormattingOptions2.InsertFinalNewLine, false)); } - [WorkItem("https://github.com/dotnet/roslyn/issues/16282")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/16282")] public async Task MoveTypeRemoveOuterInheritanceTypes() { var code = @@ -976,8 +972,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17930")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17930")] public async Task MoveTypeWithDirectives1() { var code = @@ -1029,8 +1024,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/17930")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/17930")] public async Task MoveTypeWithDirectives2() { var code = @@ -1087,8 +1081,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/21456")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/21456")] public async Task TestLeadingBlankLines1() { var code = @@ -1140,8 +1133,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/21456")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/21456")] public async Task TestLeadingBlankLines2() { var code = @@ -1193,8 +1185,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/31377")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/31377")] public async Task TestLeadingCommentInContainer() { var code = @@ -1246,8 +1237,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/31377")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/31377")] public async Task TestLeadingCommentInContainer2() { var code = @@ -1297,8 +1287,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/31377")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/31377")] public async Task TestTrailingCommentInContainer() { var code = @@ -1350,8 +1339,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/31377")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/31377")] public async Task TestTrailingCommentInContainer2() { var code = @@ -1400,8 +1388,7 @@ await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText); } - [WorkItem("https://github.com/dotnet/roslyn/issues/50329")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/50329")] public async Task MoveRecordToNewFilePreserveUsings() { var code = diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameFile.cs b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameFile.cs index 4e60c486cfb19..583b4c081385e 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameFile.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.RenameFile.cs @@ -39,8 +39,7 @@ class Inner { } await TestRenameFileToMatchTypeAsync(code, expectedDocumentName); } - [WorkItem("https://github.com/dotnet/roslyn/issues/16284")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16284")] public async Task MoreThanOneTypeInFile_RenameFile_InnerType() { var code = diff --git a/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs b/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs index e9a5d37082d97..2a7421fefc917 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/SyncNamespace/SyncNamespaceTests_ChangeNamespace.cs @@ -1879,8 +1879,7 @@ class RefClass await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/33890")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33890")] public async Task ChangeNamespace_ExtensionMethodInReducedForm() { var defaultNamespace = "A"; @@ -1935,8 +1934,7 @@ public class Class1 await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/33890")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33890")] public async Task ChangeNamespace_ExternsionMethodInRegularForm() { var defaultNamespace = "A"; @@ -1991,8 +1989,7 @@ public class Class1 await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/33890")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33890")] public async Task ChangeNamespace_ContainsBothTypeAndExternsionMethod() { var defaultNamespace = "A"; @@ -2053,8 +2050,7 @@ public class Class1 await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/33890")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33890")] public async Task ChangeNamespace_WithExtensionMethodReferencesInVBDocument() { var defaultNamespace = "A.B.C"; @@ -2111,8 +2107,7 @@ End Function await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/37891")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37891")] public async Task ChangeNamespace_WithMemberAccessReferencesInOtherDocument() { var defaultNamespace = "A"; @@ -2175,8 +2170,7 @@ Enum1 M1() await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/37891")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37891")] public async Task ChangeToGlobalNamespace_WithMemberAccessReferencesInOtherDocument() { var defaultNamespace = ""; @@ -2234,8 +2228,7 @@ Enum1 M1() await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/37891")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37891")] public async Task ChangeNamespace_WithMemberAccessReferencesInVBDocument() { var defaultNamespace = "A.B.C"; @@ -2286,8 +2279,7 @@ End Sub await TestChangeNamespaceAsync(code, expectedSourceOriginal, expectedSourceReference); } - [WorkItem("https://github.com/dotnet/roslyn/issues/37891")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37891")] public async Task ChangeToGlobalNamespace_WithMemberAccessReferencesInVBDocument() { var defaultNamespace = ""; diff --git a/src/EditorFeatures/CSharpTest/CompleteStatement/CSharpCompleteStatementCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/CompleteStatement/CSharpCompleteStatementCommandHandlerTests.cs index 321ac55db6bf0..1dc1fa2c11d55 100644 --- a/src/EditorFeatures/CSharpTest/CompleteStatement/CSharpCompleteStatementCommandHandlerTests.cs +++ b/src/EditorFeatures/CSharpTest/CompleteStatement/CSharpCompleteStatementCommandHandlerTests.cs @@ -227,7 +227,6 @@ public void ArgumentListOfMethodInvocation_SemicolonAlreadyExists() // Verbatim strings [InlineData("$$ @\"Test\"")] [InlineData(" $$@\"Test\"")] - [InlineData(" @$$\"Test\"")] [InlineData("@\"Test\"$$ ")] [InlineData("@\"Test\" $$")] @@ -241,7 +240,6 @@ public void ArgumentListOfMethodInvocation_SemicolonAlreadyExists() [InlineData("$$ \"Test\"u8")] [InlineData(" $$\"Test\"u8")] [InlineData("\"Test\"u8$$ ")] - [InlineData("\"Test\"$$u8 ")] [InlineData("\"Test\"u8 $$")] public void ArgumentListOfMethodInvocation_OutsideStringAsMethodArgument(string argument) { @@ -256,10 +254,12 @@ public void ArgumentListOfMethodInvocation_OutsideStringAsMethodArgument(string [WpfTheory] [InlineData("\"Test$$\"")] [InlineData("@\"Test$$\"")] + [InlineData(" @$$\"Test\"")] [InlineData("\"\"\"Test$$\"\"\"")] [InlineData("\"\"\"Test\"$$\"\"")] [InlineData("\"\"\"Test\"\"$$\"")] [InlineData("\"Test$$\"u8")] + [InlineData("\"Test\"$$u8 ")] public void ArgumentListOfMethodInvocation_InsideStringAsMethodArgument(string argument) { var code = CreateTestWithMethodCall($@"var test = Console.WriteLine({argument})"); @@ -1261,8 +1261,7 @@ static void Main(string[] args) VerifyTypingSemicolon(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/32250")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/32250")] public void ForLoopInitializers() { var code = @@ -1290,8 +1289,7 @@ static void Main(string[] args) VerifyTypingSemicolon(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/32250")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/32250")] public void ForLoopInitializers2() { var code = @@ -3425,8 +3423,7 @@ void M() VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/35260")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/35260")] public void DoWhile5() { var code = @@ -3462,8 +3459,7 @@ void M() VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/35260")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/35260")] public void DoWhile6() { var code = @@ -3990,8 +3986,7 @@ public void DoNotComplete_UnterminatedCharLiteral(string literal) VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34176")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34176")] public void DoNotComplete_VerbatimStringAsMethodArgument_EndOfLine_NotEndOfString() { var code = @" @@ -4001,8 +3996,7 @@ public void DoNotComplete_VerbatimStringAsMethodArgument_EndOfLine_NotEndOfStrin VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34176")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34176")] public void DoNotComplete_VerbatimStringAsMethodArgument_EndOfString_NotEndOfLine() { @@ -4183,8 +4177,7 @@ public void DoNotComplete_Using3() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/33851")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/33851")] public void AtEndOfLineOutsideParens() { var code = @" @@ -4202,8 +4195,7 @@ void M() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/33851")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/33851")] public void OutsideParensBeforeSpaceDot() { var code = @" @@ -4220,8 +4212,7 @@ void M() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34666")] public void BeforeAttribute() { var code = @" @@ -4238,8 +4229,7 @@ public void M() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34666")] public void ElementBindingExpression() { var code = @" @@ -4263,8 +4253,7 @@ void M() VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34666")] public void BeforeElementBindingExpression() { var code = @" @@ -4279,8 +4268,7 @@ void M() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34666")] public void AfterElementBindingExpression() { var code = @" @@ -4296,8 +4284,7 @@ void M() } [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void ImplicitElementAccessSyntax() { var code = @" @@ -4325,8 +4312,7 @@ void M() VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34666")] public void BeforeImplicitElementAccessSyntax() { var code = @" @@ -4354,8 +4340,7 @@ void M() VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34666")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34666")] public void AfterImplicitElementAccessSyntax() { var code = @" @@ -4383,8 +4368,7 @@ void M() VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void AttributeParsedAsElementAccessExpression() { var code = @" @@ -4406,8 +4390,7 @@ internal class TestMethodAttribute : Attribute VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void MemberAccessOffOfMethod() { var code = @" @@ -4431,8 +4414,7 @@ static void Main(string[] args) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void LinqQuery() { var code = @" @@ -4466,8 +4448,7 @@ void Main(string[] args) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void LinqQuery2() { var code = @" @@ -4499,8 +4480,7 @@ void Main(string[] args) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void BinaryExpression() { var code = @" @@ -4532,8 +4512,7 @@ private int Foo(int v) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void BinaryExpression2() { var code = @" @@ -4565,8 +4544,7 @@ private int Foo(int v) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void AsOperator() { var code = @" @@ -4598,8 +4576,7 @@ object Foo(int v) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void TernaryOperator() { var code = @" @@ -4635,8 +4612,7 @@ private int Foo(int j) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34983")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34983")] public void SemicolonInCharacterLiteral() { var code = @" @@ -4668,8 +4644,7 @@ void M(char c) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/35260")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/35260")] public void IncompleteLambda() { var code = @" @@ -4710,8 +4685,7 @@ private void M(Func p) { } internal override ICommandHandler GetCommandHandler(EditorTestWorkspace workspace) => workspace.ExportProvider.GetExportedValues().OfType().Single(); - [WorkItem("https://github.com/dotnet/roslyn/issues/32337")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/32337")] public void ArgumentList_MultipleCharsSelected() { var code = CreateTestWithMethodCall(@"var test = ClassC.MethodM([|x[0]|], x[1])"); @@ -4719,8 +4693,7 @@ public void ArgumentList_MultipleCharsSelected() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_DelegateDeclaration() { var code = @" @@ -4736,8 +4709,7 @@ class C VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_DelegateDeclaration2() { var code = @" @@ -4748,8 +4720,7 @@ class C VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_DelegateDeclaration3() { var code = @" @@ -4765,8 +4736,7 @@ class C VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_MultilineDelegateDeclaration() { var code = @" @@ -4786,8 +4756,7 @@ delegate void Del(string str, VerifyTypingSemicolon(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_Constructor() { var code = @" @@ -4800,8 +4769,7 @@ public D($$) VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_Destructor() { var code = @" @@ -4818,8 +4786,7 @@ public D() VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/34051")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/34051")] public void ParameterList_MethodDeclaration() { var code = @" @@ -4832,8 +4799,7 @@ void M($$) VerifyNoSpecialSemicolonHandling(code); } - [WorkItem("https://github.com/dotnet/roslyn/issues/54709")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/54709")] public void YieldReturn() { var code = @" @@ -4855,6 +4821,24 @@ private static IEnumerable M() VerifyTypingSemicolon(code, expected); } + [WorkItem("https://github.com/dotnet/roslyn/issues/71933")] + [WpfFact] + public void InsideDisabledCode() + { + var code = CreateTestWithMethodCall(""" + + Console.WriteLine( + #if false + // Comment$$ + "$$"$$ + #endif + ); + + """); + + VerifyNoSpecialSemicolonHandling(code); + } + [WorkItem("https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/917499")] [WpfTheory] [InlineData("/$$* comments */")] @@ -4889,8 +4873,7 @@ public void NearComments(string argument) VerifyTypingSemicolon(code, expected); } - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/923157")] - [WpfFact] + [WpfFact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/923157")] public void BrokenCode_ReturnIfCaretDoesNotMove() { var code = @" @@ -4979,8 +4962,7 @@ public void Test(string myString) VerifyNoSpecialSemicolonHandling(code); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/70224")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/70224")] public void TestNotBeforeKeywordInSwitchExpression() { var code = @" diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs index 36a12b89f69f1..6c863e54339b4 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs @@ -54,8 +54,7 @@ public class b : a }", "goo()"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543799")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543799")] public async Task InheritedParameterDefaultValue1() { await VerifyItemExistsAsync(@"public class a @@ -69,8 +68,7 @@ public class b : a }", "goo(int x = 42)", "void a.goo([int x = 42])"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543799")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543799")] public async Task InheritedParameterDefaultValue2() { await VerifyItemExistsAsync(@"public class a @@ -652,8 +650,7 @@ class SomeClass : Derived await VerifyItemExistsAsync(markup, "Goo()", "void Derived.Goo()"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543748")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543748")] public async Task NotOfferedBaseClassMember() { var markup = @"abstract class Base @@ -788,8 +785,7 @@ public class SomeClass : Base await VerifyItemIsAbsentAsync(markup, "Goo(T t, S s)"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543756")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543756")] public async Task ParameterTypeSimplified() { var markup = @"using System; @@ -908,8 +904,7 @@ public class SomeClass : Base await VerifyItemExistsAsync(markup, "goo(int x, out string y)", "void Base.goo(int x, out string y)"); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529714")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529714")] public async Task GenericMethodTypeParametersNotRenamed() { var markup = @"abstract class CGoo @@ -948,8 +943,7 @@ public override bool Equals(object obj) await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Equals(object obj)", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529714")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529714")] public async Task CommitGenericMethodTypeParametersNotRenamed() { var markupBeforeCommit = @"abstract class CGoo @@ -1027,8 +1021,7 @@ public override bool Equals(object obj) await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Equals(object obj)", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543798")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543798")] public async Task CommitOptionalParameterValuesAreGenerated() { var markupBeforeCommit = @"using System; @@ -2243,8 +2236,7 @@ public override void goo(int x, out string y) await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo(int x, out string y)", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] public async Task TestUnsafe1() { var markupBeforeCommit = @@ -2279,8 +2271,7 @@ public override void F() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "F()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] public async Task TestUnsafe2() { var markupBeforeCommit = @@ -2315,8 +2306,7 @@ public override unsafe void F() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "F()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] public async Task TestUnsafe3() { var markupBeforeCommit = @@ -2351,8 +2341,7 @@ public override unsafe void F() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "F()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544560")] public async Task TestUnsafe4() { var markupBeforeCommit = @@ -2387,8 +2376,7 @@ public override unsafe void F(int* i) await VerifyCustomCommitProviderAsync(markupBeforeCommit, "F(int* i)", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545534")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545534")] public async Task TestPrivateVirtualProperty() { var markupBeforeCommit = @@ -2428,8 +2416,7 @@ public override int Goo await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/636706")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/636706")] public async Task CrossLanguageParameterizedPropertyOverride() { var vbFile = @"Public Class Goo @@ -2505,8 +2492,7 @@ public override void set_Bar(int bay, int value) #region "Commit: With Trivia" - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529199")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529199")] public async Task CommitSurroundingTriviaDirective() { var markupBeforeCommit = @"class Base @@ -2538,8 +2524,7 @@ public override void goo() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529199")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529199")] public async Task CommitBeforeTriviaDirective() { var markupBeforeCommit = @"class Base @@ -2603,8 +2588,7 @@ public override void goo() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529199")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529199")] public async Task CommitBeforeComment() { var markupBeforeCommit = @"class Base @@ -2702,8 +2686,7 @@ public override void goo() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/736742")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/736742")] public async Task AcrossPartialTypes1() { var file1 = @"partial class c @@ -2758,8 +2741,7 @@ public override bool Equals(object obj) } } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/736742")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/736742")] public async Task AcrossPartialTypes2() { var file1 = @"partial class c @@ -3093,8 +3075,7 @@ static void Main(string[] args) Assert.Equal(change.Span, TextSpan.FromBounds(136, 145)); } - [WorkItem("https://github.com/dotnet/roslyn/issues/8257")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/8257")] public async Task NotImplementedQualifiedWhenSystemUsingNotPresent_Property() { var markupBeforeCommit = @"abstract class C @@ -3131,8 +3112,7 @@ public override int goo await VerifyCustomCommitProviderAsync(markupBeforeCommit, "goo", expectedCodeAfterCommit); } - [WorkItem("https://github.com/dotnet/roslyn/issues/8257")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/8257")] public async Task NotImplementedQualifiedWhenSystemUsingNotPresent_Method() { var markupBeforeCommit = @"abstract class C @@ -3289,8 +3269,7 @@ public override void M(in int x) Assert.Equal(after, actualCodeAfterCommit); } - [WorkItem("https://github.com/dotnet/roslyn/issues/39909")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/39909")] public async Task CommitAddsMissingImports() { var markupBeforeCommit = @" diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs index 8b0b73170a93f..a73034379ca24 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs @@ -32,8 +32,7 @@ internal override OptionsCollection NonCompletionOptions { CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement } }; - [WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")] - [WpfFact] + [WpfFact, WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")] public async Task CommitProducesExpressionBodyProperties() { var markupBeforeCommit = """ @@ -61,8 +60,7 @@ class C : B await VerifyCustomCommitProviderAsync(markupBeforeCommit, "A", expectedCodeAfterCommit); } - [WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")] - [WpfFact] + [WpfFact, WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")] public async Task CommitProducesExpressionBodyGetterOnlyProperty() { var markupBeforeCommit = """ @@ -90,8 +88,7 @@ class C : B await VerifyCustomCommitProviderAsync(markupBeforeCommit, "A", expectedCodeAfterCommit); } - [WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")] - [WpfFact] + [WpfFact, WorkItem(16331, "https://github.com/dotnet/roslyn/issues/16334")] public async Task CommitProducesExpressionBodyMethod() { var markupBeforeCommit = """ diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs index 43b9d639c8d20..22a47c9be17d5 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs @@ -721,8 +721,7 @@ void Goo() await VerifyNoItemsExistAsync(text); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")] public async Task CommitAsync() { var markupBeforeCommit = """ @@ -753,8 +752,7 @@ async partial void Goo() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")] public async Task CommitAsyncExtended() { var markupBeforeCommit = """ @@ -785,8 +783,7 @@ public async partial void Goo() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo()", expectedCodeAfterCommit); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578078")] public async Task AmbiguityCommittingWithParen() { var markupBeforeCommit = """ @@ -817,8 +814,7 @@ partial void Goo() await VerifyCustomCommitProviderAsync(markupBeforeCommit, "Goo()", expectedCodeAfterCommit, commitChar: '('); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965677")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965677")] public async Task NoDefaultParameterValues() { var text = """ @@ -850,8 +846,7 @@ partial void PMethod(int i) await VerifyCustomCommitProviderAsync(text, "PMethod(int i)", expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965677")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/965677")] public async Task NoDefaultParameterValuesExtended() { var text = """ @@ -883,8 +878,7 @@ public partial void PMethod(int i) await VerifyCustomCommitProviderAsync(text, "PMethod(int i)", expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/26388")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/26388")] public async Task ExpressionBodyMethod() { using var workspaceFixture = GetOrCreateWorkspaceFixture(); diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index a39b124289f82..1e4ee5e2236d4 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -1605,21 +1605,18 @@ public async Task Parameters_07(string prefix) await VerifyItemExistsAsync("call(" + prefix + "$$)", "args", sourceCodeKind: SourceCodeKind.Regular); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/55969")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/55969")] public async Task Parameters_TopLevelStatement_1() => await VerifyItemIsAbsentAsync(@"$$", "args", sourceCodeKind: SourceCodeKind.Regular); - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/55969")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/55969")] public async Task Parameters_TopLevelStatement_2() => await VerifyItemExistsAsync( @"using System; Console.WriteLine(); $$", "args", sourceCodeKind: SourceCodeKind.Regular); - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/55969")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/55969")] public async Task Parameters_TopLevelStatement_3() => await VerifyItemIsAbsentAsync( @"using System; @@ -5202,8 +5199,7 @@ await VerifyItemInEditorBrowsableContextsAsync( } [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/522440")] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/674611")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/674611")] public async Task EditorBrowsable_Property_BrowsableStateNever() { var markup = @" @@ -9444,8 +9440,7 @@ void M() await VerifyItemExistsAsync(markup, "Bar"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7932")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7932")] public async Task ExtensionMethodWithinSameClassOfferedForCompletion() { var markup = @" @@ -9461,8 +9456,7 @@ static void TestA(this string s) { } await VerifyItemExistsAsync(markup, "TestA"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/7932")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7932")] public async Task ExtensionMethodWithinParentClassOfferedForCompletion() { var markup = @" diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs index a91f92e410354..855594578f61e 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs @@ -1035,8 +1035,7 @@ class Bat AssertRelativeOrder(new List() { "SomeType", "SomeTypeWithLongerName" }, completionList.ItemsList.ToImmutableArray()); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/35540")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")] public async Task AttributeTypeInAttributeNameContext() { var file1 = @" @@ -1093,8 +1092,7 @@ class Program { } await VerifyCustomCommitProviderAsync(markup, "My", expectedCodeAfterCommit, sourceCodeKind: kind); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/35540")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")] public async Task AttributeTypeInNonAttributeNameContext() { var file1 = @" @@ -1156,8 +1154,7 @@ class Program await VerifyCustomCommitProviderAsync(markup, "MyAttribute", expectedCodeAfterCommit, sourceCodeKind: kind); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/35540")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")] public async Task AttributeTypeWithoutSuffixInAttributeNameContext() { // attribute suffix isn't capitalized @@ -1214,8 +1211,7 @@ class Program { } await VerifyCustomCommitProviderAsync(markup, "Myattribute", expectedCodeAfterCommit, sourceCodeKind: kind); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/35540")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")] public async Task AttributeTypeWithoutSuffixInNonAttributeNameContext() { // attribute suffix isn't capitalized @@ -1277,8 +1273,7 @@ class Program await VerifyCustomCommitProviderAsync(markup, "Myattribute", expectedCodeAfterCommit, sourceCodeKind: kind); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/35540")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")] public async Task VBAttributeTypeWithoutSuffixInAttributeNameContext() { var file1 = @" diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs index ab5c51ac79204..9c6dd8ca0eedc 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs @@ -1093,8 +1093,7 @@ public struct Goo(string MyParameter); """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69293")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69293")] public async Task DelegateParamRef() { await VerifyItemsExistAsync(""" diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs index 42403512dc77a..5c6e0adb9be54 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs @@ -155,7 +155,7 @@ public void DiagnosticServiceIsSafeAgainstAnalyzerExceptions_2() exceptions.Add(e); } - Assert.True(exceptions.Count == 0); + Assert.Empty(exceptions); } [Fact] diff --git a/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs b/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs index 6b47bf3c4e168..4d4155d716131 100644 --- a/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs +++ b/src/EditorFeatures/CSharpTest/DocumentationComments/DocumentationCommentTests.cs @@ -494,8 +494,7 @@ void M<@T>(int @int) { } VerifyTypingCharacter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538699")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538699")] public void TypingCharacter_VoidMethod2() { var code = @@ -745,8 +744,7 @@ public void TypingCharacter_NotInsideCtor() VerifyTypingCharacter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/59081")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/59081")] public void TypingCharacter_NotInTopLevel() { var code = @" @@ -766,8 +764,7 @@ public void TypingCharacter_NotInTopLevel() VerifyTypingCharacter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/59081")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/59081")] public void TypingCharacter_NotInNamespace() { var code = @" @@ -807,8 +804,7 @@ class C VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/4817")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/4817")] public void PressingEnter_InsertComment_Class1_AutoGenerateXmlDocCommentsOff() { var code = @@ -959,8 +955,7 @@ void Goo() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537513")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537513")] public void PressingEnter_NotInterleavedInClassName1() { var code = @@ -977,8 +972,7 @@ public void PressingEnter_NotInterleavedInClassName1() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537513")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537513")] public void PressingEnter_NotInterleavedInClassName2() { var code = @@ -995,8 +989,7 @@ public void PressingEnter_NotInterleavedInClassName2() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537513")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537513")] public void PressingEnter_NotInterleavedInClassName3() { var code = @@ -1014,8 +1007,7 @@ public void PressingEnter_NotInterleavedInClassName3() } [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537514")] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537532")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537532")] public void PressingEnter_NotAfterClassName1() { var code = @@ -1032,8 +1024,7 @@ public void PressingEnter_NotAfterClassName1() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537552")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537552")] public void PressingEnter_NotAfterClassName2() { var code = @@ -1050,8 +1041,7 @@ public void PressingEnter_NotAfterClassName2() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537535")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537535")] public void PressingEnter_NotAfterCtorName() { var code = @@ -1070,8 +1060,7 @@ public void PressingEnter_NotAfterCtorName() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537511")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537511")] public void PressingEnter_NotInsideCtor() { var code = @@ -1096,8 +1085,7 @@ public void PressingEnter_NotInsideCtor() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537550")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537550")] public void PressingEnter_NotBeforeDocComment() { var code = @@ -1277,8 +1265,7 @@ class C VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538702")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538702")] public void PressingEnter_InsertSlashes8() { var code = @@ -1367,8 +1354,7 @@ void Goo(int i) VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/4817")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/4817")] public void PressingEnter_InsertSlashes12_AutoGenerateXmlDocCommentsOff() { var code = @@ -1413,8 +1399,7 @@ class C VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538701")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538701")] public void PressingEnter_DoNotInsertSlashes2() { var code = @@ -1456,8 +1441,7 @@ public void PressingEnter_ExtraSlashesAfterExteriorTrivia() VerifyPressingEnter(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542426")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542426")] public void PressingEnter_PreserveParams() { var code = @@ -1479,8 +1463,7 @@ static void Main(string[] args) VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2091")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2091")] public void PressingEnter_InTextBeforeSpace() { const string code = @@ -1509,8 +1492,7 @@ void M() VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2108")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2108")] public void PressingEnter_Indentation1() { const string code = @@ -1539,8 +1521,7 @@ void M() VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2108")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2108")] public void PressingEnter_Indentation2() { const string code = @@ -1569,8 +1550,7 @@ void M() VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2108")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2108")] public void PressingEnter_Indentation3() { const string code = @@ -1599,8 +1579,7 @@ void M() VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2108")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2108")] public void PressingEnter_Indentation4() { const string code = @@ -1629,8 +1608,7 @@ void M() VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2108")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2108")] public void PressingEnter_Indentation5_UseTabs() { const string code = @@ -1659,8 +1637,7 @@ void M() VerifyPressingEnter(code, expected, useTabs: true); } - [WorkItem("https://github.com/dotnet/roslyn/issues/5486")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/5486")] public void PressingEnter_Selection1() { var code = @@ -1682,8 +1659,7 @@ class C VerifyPressingEnter(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/5486")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/5486")] public void PressingEnter_Selection2() { var code = @@ -1845,8 +1821,7 @@ struct R(string S, int I);"; VerifyInsertCommentCommand(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/4817")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/4817")] public void Command_Class_AutoGenerateXmlDocCommentsOff() { var code = @@ -1868,8 +1843,7 @@ class C }); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538714")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538714")] public void Command_BeforeClass1() { var code = @@ -1885,8 +1859,7 @@ class C { }"; VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538714")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538714")] public void Command_BeforeClass2() { var code = @@ -1904,8 +1877,7 @@ class C { }"; VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538714")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538714")] public void Command_BeforeClass3() { var code = @@ -1927,8 +1899,7 @@ class C { } VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527604")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527604")] public void Command_Class_NotIfMultilineDocCommentExists() { var code = @@ -2005,8 +1976,7 @@ public void Command_Method_NotIfCommentExists() VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] public void Command_FirstClassOnLine() { var code = @"$$class C { } class D { }"; @@ -2020,8 +1990,7 @@ class C { } class D { }"; VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] public void Command_NotOnSecondClassOnLine() { var code = @"class C { } $$class D { }"; @@ -2031,8 +2000,7 @@ public void Command_NotOnSecondClassOnLine() VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] public void Command_FirstMethodOnLine() { var code = @@ -2053,8 +2021,7 @@ public void Command_FirstMethodOnLine() VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538482")] public void Command_NotOnSecondMethodOnLine() { var code = @@ -2072,8 +2039,7 @@ public void Command_NotOnSecondMethodOnLine() VerifyInsertCommentCommand(code, expected); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/917904")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/917904")] public void TestUseTab() { var code = @@ -2103,8 +2069,7 @@ public Class1() VerifyTypingCharacter(code, expected, useTabs: true); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineAbove1() { const string code = @@ -2133,8 +2098,7 @@ void M() VerifyOpenLineAbove(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineAbove2() { const string code = @@ -2163,8 +2127,7 @@ void M() VerifyOpenLineAbove(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineAbove3() { const string code = @@ -2195,8 +2158,7 @@ void M() VerifyOpenLineAbove(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineAbove4_Tabs() { const string code = @@ -2225,8 +2187,7 @@ void M() VerifyOpenLineAbove(code, expected, useTabs: true); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineBelow1() { const string code = @@ -2255,8 +2216,7 @@ void M() VerifyOpenLineBelow(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineBelow2() { const string code = @@ -2285,8 +2245,7 @@ void M() VerifyOpenLineBelow(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineBelow3() { const string code = @@ -2305,8 +2264,7 @@ public void TestOpenLineBelow3() VerifyOpenLineBelow(code, expected); } - [WorkItem("https://github.com/dotnet/roslyn/issues/2090")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/2090")] public void TestOpenLineBelow4_Tabs() { const string code = @@ -2335,8 +2293,7 @@ void M() VerifyOpenLineBelow(code, expected, useTabs: true); } - [WorkItem(468638, @"https://devdiv.visualstudio.com/DevDiv/NET%20Developer%20Experience%20IDE/_workitems/edit/468638")] - [WpfFact] + [WpfFact, WorkItem(468638, @"https://devdiv.visualstudio.com/DevDiv/NET%20Developer%20Experience%20IDE/_workitems/edit/468638")] public void VerifyEnterWithTrimNewLineEditorConfigOption() { const string code = diff --git a/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs index cf0cf40ee0afa..2503f2b408c29 100644 --- a/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs +++ b/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs @@ -40,8 +40,7 @@ void M() testState.AssertShowing("C_MyEvent"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20999")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20999")] public async Task HandlerName_EventInThisClass_CamelCaseRule() { var markup = @" diff --git a/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs index 742abf24e386d..85b641d450c95 100644 --- a/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs @@ -1970,5 +1970,36 @@ await TestExtractInterfaceCommandCSharpAsync( markup, expectedSuccess: false); } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ExtractInterface)] + public async Task TestStruct4() + { + var markup = + """ + namespace Test + { + struct $$Whatever + { + public int I { get; set; } + } + } + """; + + var expectedInterfaceCode = + """ + namespace Test + { + interface IWhatever + { + int I { get; set; } + } + } + """; + + await TestExtractInterfaceCommandCSharpAsync( + markup, + expectedSuccess: true, + expectedInterfaceCode: expectedInterfaceCode); + } } } diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs index a41234cb2ff84..ef5d1071b242c 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs @@ -474,8 +474,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideSingleLineRegularComment_1() { @@ -503,8 +502,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideSingleLineRegularComment_2() { @@ -532,8 +530,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideMultiLineRegularComment_1() { @@ -559,8 +556,7 @@ static void Main(int a/* { */, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideMultiLineRegularComment_2() { @@ -588,8 +584,7 @@ static void Main(int a/* { AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideMultiLineRegularComment_3() { @@ -617,8 +612,7 @@ static void Main(int a/* { AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideSingleLineDocComment_1() { @@ -646,8 +640,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideSingleLineDocComment_2() { @@ -675,8 +668,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideMultiLineDocComment_1() { @@ -704,8 +696,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideMultiLineDocComment_2() { @@ -735,8 +726,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideMultiLineDocComment_3() { @@ -766,8 +756,7 @@ static void Main(int a, int b) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideInactiveCode() { @@ -801,8 +790,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideStringLiteral() { @@ -828,8 +816,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideCharLiteral() { @@ -855,8 +842,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/449")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/449")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] public void NoFormattingInsideCommentsOfPreprocessorDirectives() { @@ -886,8 +872,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void ColonInSwitchCase() { @@ -921,8 +906,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void ColonInDefaultSwitchCase() { @@ -989,8 +973,7 @@ static void Main() AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void ColonInLabeledStatement() { @@ -1016,8 +999,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void DoNotFormatColonInTargetAttribute() { @@ -1039,8 +1021,7 @@ class C : Attribute AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void DoNotFormatColonInBaseList() { @@ -1058,8 +1039,7 @@ class C : Attribute AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void DoNotFormatColonInThisConstructor() { @@ -1091,8 +1071,7 @@ class Goo AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void DoNotFormatColonInConditionalOperator() { @@ -1118,8 +1097,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void DoNotFormatColonInArgument() { @@ -1145,8 +1123,7 @@ static void Main(string[] args) AssertFormatAfterTypeChar(code, expected); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/464")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/464")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] public void DoNotFormatColonInTypeParameter() { diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs index bc142d4e1265b..bc0396a98e08b 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs @@ -29,8 +29,7 @@ public class SmartIndenterEnterOnTokenTests : CSharpFormatterTestsBase { public SmartIndenterEnterOnTokenTests(ITestOutputHelper output) : base(output) { } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537808")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537808")] public async Task MethodBody1() { var code = @"class Class1 @@ -577,8 +576,7 @@ await AssertIndentUsingSmartTokenFormatterAsync( expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537802")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537802")] public async Task EmbededStatement() { var code = @"class Program @@ -599,8 +597,7 @@ await AssertIndentUsingSmartTokenFormatterAsync( expectedIndentation: 8); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537808")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537808")] public async Task MethodBraces1() { var code = @"class Class1 @@ -616,8 +613,7 @@ await AssertIndentUsingSmartTokenFormatterAsync( expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537808")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537808")] public async Task MethodBraces2() { var code = @"class Class1 @@ -634,8 +630,7 @@ await AssertIndentUsingSmartTokenFormatterAsync( expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537795")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537795")] public async Task Property1() { var code = @"class C @@ -654,8 +649,7 @@ await AssertIndentUsingSmartTokenFormatterAsync( expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537563")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537563")] public async Task Class1() { var code = @"class C diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs index 2972f040745a2..980f9ab7a1b69 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterTests.cs @@ -691,8 +691,7 @@ public void AfterTopLevelAttribute() expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537802")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537802")] public void EmbeddedStatement() { var code = @"class Program @@ -737,8 +736,7 @@ static void Main(string[] args) expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537883")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537883")] public void EnterAfterComment() { var code = @"class Program @@ -757,8 +755,7 @@ static void Main(string[] args) expectedIndentation: 8); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538121")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538121")] public void NestedBlock1() { var code = @"class Program @@ -1273,8 +1270,7 @@ static void Main(string[] args) expectedIndentation: 24); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538333")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538333")] public void Statement1() { var code = @"class Program @@ -1288,8 +1284,7 @@ void Test() { } expectedIndentation: 4); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538933")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538933")] public void EndOfFile1() { var code = @"class Program @@ -1306,8 +1301,7 @@ void Test() expectedIndentation: 8); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539059")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539059")] public void VerbatimString() { var code = @"class Program @@ -1380,8 +1374,7 @@ void Test() expectedIndentation: 12); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/60946")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/60946")] public void RawString4() { var code = @"class Program @@ -1400,8 +1393,7 @@ void Test() expectedIndentation: 16); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/60946")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/60946")] public void RawString5() { var code = @"class Program @@ -1536,8 +1528,7 @@ void Test() expectedIndentation: 12); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/60946")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/60946")] public void InterpolatedRawString4() { var code = @"class Program @@ -1556,8 +1547,7 @@ void Test() expectedIndentation: 16); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/60946")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/60946")] public void InterpolatedRawString5() { var code = @"class Program @@ -1595,8 +1585,7 @@ public void InterpolatedRawString6() expectedIndentation: 0); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/60946")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/60946")] public void InterpolatedRawString7() { var code = @"class Program @@ -1621,8 +1610,7 @@ void Test() expectedIndentation: 16); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/60946")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/60946")] public void InterpolatedRawString8() { var code = @"class Program @@ -1759,8 +1747,7 @@ public void AfterIfWithSingleStatementInTopLevelMethod_Bug7291_2() } [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540634")] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544268")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544268")] public void FirstArgumentInArgumentList() { var code = @"class Program @@ -2260,8 +2247,7 @@ static void Main(string[] args) expectedIndentation: 12); } - [WorkItem(9216, "DevDiv_Projects/Roslyn")] - [WpfFact] + [WpfFact, WorkItem(9216, "DevDiv_Projects/Roslyn")] public void FollowPreviousLineInMultilineStatements() { var code = @"class Program @@ -2892,8 +2878,7 @@ static void Main(string[] args) expectedIndentation: 36); } - [WorkItem("https://github.com/dotnet/roslyn/issues/5495")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/5495")] public void AfterBadQueryContinuationWithSelectOrGroupClause() { var code = @"using System.Collections.Generic; @@ -2942,8 +2927,7 @@ class UserViewModel expectedIndentation: 25); } - [WorkItem("https://github.com/dotnet/roslyn/issues/5495")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/5495")] public void AfterPartialFromClause() { var code = @" @@ -2964,8 +2948,7 @@ void M() expectedIndentation: 16); } - [WorkItem("https://github.com/dotnet/roslyn/issues/5635")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/5635")] public void ConstructorInitializerMissingBaseOrThisKeyword() { var code = @" @@ -3177,8 +3160,7 @@ public void Test() expectedIndentation: 12); } - [WorkItem("https://github.com/dotnet/roslyn/issues/28752")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/28752")] public void EnterAfterBlankLineAfterCommentedOutCode1() { var code = @"class Test @@ -3202,8 +3184,7 @@ public void Test() expectedIndentation: 8); } - [WorkItem("https://github.com/dotnet/roslyn/issues/28752")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/28752")] public void EnterAfterBlankLineAfterCommentedOutCode2() { var code = @" @@ -3233,8 +3214,7 @@ class T expectedIndentation: 4); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38819")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38819")] public void IndentationOfReturnInFileWithTabs1() { var code = @" diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs index 090c4b54ad6ef..602369a537933 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs @@ -2000,8 +2000,7 @@ void Method() await AutoFormatOnCloseBraceAsync(code, expected, SyntaxKind.OpenBraceToken); } - [WpfFact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537555")] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537555")] public async Task SingleLine() { var code = @"class C { void M() { C.M( );$$ } }"; @@ -2029,8 +2028,7 @@ public async Task CharLiterals() await AutoFormatOnMarkerAsync(code, expected, SyntaxKind.CharacterLiteralToken, SyntaxKind.None); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/44423")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44423")] public async Task CharLiterals1() { var code = @"';$$"; @@ -2172,8 +2170,7 @@ void Method() await AutoFormatOnSemicolonAsync(code, expected, SyntaxKind.OpenBraceToken); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537776")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537776")] public async Task DisappearedTokens() { var code = @"class Class1 @@ -2224,8 +2221,7 @@ await AutoFormatOnSemicolonAsync( SyntaxKind.OpenBraceToken); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537793")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537793")] public async Task Delegate1() { var code = @"delegate void MyDelegate(int a,int b);$$"; @@ -2238,8 +2234,7 @@ await AutoFormatOnSemicolonAsync( SyntaxKind.DelegateKeyword); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537827")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537827")] public async Task DoubleInitializer() { var code = @"class C @@ -2264,8 +2259,7 @@ await AutoFormatOnCloseBraceAsync( SyntaxKind.OpenBraceToken); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537825")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537825")] public async Task MissingToken1() { var code = @"public class Class1 @@ -2760,7 +2754,7 @@ void Main() await AutoFormatOnSemicolonAsync( code, expected, - SyntaxKind.OpenBraceToken); + SyntaxKind.None); } [WpfTheory] diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/DiagnosticAnalyzerQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/DiagnosticAnalyzerQuickInfoSourceTests.cs index ab899f4b5c56b..8c88b364c4756 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/DiagnosticAnalyzerQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/DiagnosticAnalyzerQuickInfoSourceTests.cs @@ -29,8 +29,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.QuickInfo [Trait(Traits.Feature, Traits.Features.QuickInfo)] public class DiagnosticAnalyzerQuickInfoSourceTests { - [WorkItem("https://github.com/dotnet/roslyn/issues/46604")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/46604")] public async Task ErrorTitleIsShownOnDisablePragma() { await TestInMethodAsync( @@ -41,8 +40,7 @@ await TestInMethodAsync( """, GetFormattedErrorTitle(ErrorCode.WRN_UnreferencedVarAssg)); } - [WorkItem("https://github.com/dotnet/roslyn/issues/46604")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/46604")] public async Task ErrorTitleIsShownOnRestorePragma() { await TestInMethodAsync( @@ -53,8 +51,7 @@ await TestInMethodAsync( """, GetFormattedErrorTitle(ErrorCode.WRN_UnreferencedVarAssg)); } - [WorkItem("https://github.com/dotnet/roslyn/issues/46604")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/46604")] public async Task DisabledWarningNotExistingInCodeIsDisplayedByTitleWithoutCodeDetails() { await TestInMethodAsync( @@ -118,8 +115,7 @@ await TestInMethodAsync( ", GetFormattedErrorTitle((ErrorCode)errorCode)); } - [WorkItem("https://github.com/dotnet/roslyn/issues/46604")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/46604")] public async Task ErrorTitleIsShwonInSupressMessageAttribute() { await TestAsync( diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs index 34b0f64c16438..7ff277d6ac53b 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs @@ -70,8 +70,7 @@ await TestInMethodAndScriptAsync( {"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_0() { await TestInMethodAndScriptAsync( @@ -83,8 +82,7 @@ await TestInMethodAndScriptAsync( "{"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_1() { await TestInMethodAndScriptAsync( @@ -100,8 +98,7 @@ await TestInMethodAndScriptAsync( {"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_2() { await TestInMethodAndScriptAsync( @@ -116,8 +113,7 @@ await TestInMethodAndScriptAsync( {"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_3() { await TestInMethodAndScriptAsync( @@ -136,8 +132,7 @@ await TestInMethodAndScriptAsync( // comment"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_4() { await TestInMethodAndScriptAsync( @@ -151,8 +146,7 @@ await TestInMethodAndScriptAsync( /* comment */"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_5() { await TestInMethodAndScriptAsync( @@ -167,8 +161,7 @@ await TestInMethodAndScriptAsync( {"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_6() { await TestInMethodAndScriptAsync( @@ -190,8 +183,7 @@ await TestInMethodAndScriptAsync( {"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_7() { await TestInMethodAndScriptAsync( @@ -214,8 +206,7 @@ await TestInMethodAndScriptAsync( {"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_8() { await TestInMethodAndScriptAsync( @@ -236,8 +227,7 @@ await TestInMethodAndScriptAsync( // part 2"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_9() { await TestInClassAsync( @@ -252,8 +242,7 @@ await TestInClassAsync( "{"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/325")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/325")] public async Task ScopeBrackets_10() { await TestInMethodAndScriptAsync( diff --git a/src/EditorFeatures/CSharpTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.cs b/src/EditorFeatures/CSharpTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.cs index 1ac5420a62481..a0965b85d7a1e 100644 --- a/src/EditorFeatures/CSharpTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.cs @@ -184,8 +184,7 @@ void Goo(int a, int b) await TestAsync(markup, [new SignatureHelpTestItem("void C.Goo(int a, int b)", "Summary for Goo", "Param b", currentParameterIndex: 1)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/26713")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26713")] public async Task TestDelegateParameterWithDocumentation_Invoke() { var markup = """ @@ -204,8 +203,7 @@ void M(SomeDelegate theDelegate) await TestAsync(markup, [new SignatureHelpTestItem("void SomeDelegate(int a)", parameterDocumentation: "Parameter docs", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/26713")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26713")] public async Task TestDelegateParameterWithDocumentation_Invoke2() { var markup = """ @@ -224,8 +222,7 @@ void M(SomeDelegate theDelegate) await TestAsync(markup, [new SignatureHelpTestItem("void SomeDelegate.Invoke(int a)", parameterDocumentation: "Parameter docs", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/26713")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26713")] public async Task TestDelegateParameterWithDocumentation_BeginInvoke() { var markup = """ @@ -244,8 +241,7 @@ void M(SomeDelegate theDelegate) await TestAsync(markup, [new SignatureHelpTestItem("System.IAsyncResult SomeDelegate.BeginInvoke(int a, System.AsyncCallback callback, object @object)", parameterDocumentation: "Parameter docs", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/26713")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26713")] public async Task TestDelegateParameterWithDocumentation_BeginInvoke2() { var markup = """ @@ -425,8 +421,7 @@ public class D await TestAsync(markup); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539712")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539712")] public async Task TestInvocationOnNamedType() { var markup = """ @@ -453,8 +448,7 @@ public double Goo(double x, double y) await TestAsync(markup, [new SignatureHelpTestItem("double C.Goo(double x)", string.Empty, string.Empty, currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539712")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539712")] public async Task TestInvocationOnInstance() { var markup = """ @@ -481,8 +475,7 @@ public double Goo(double x, double y) await TestAsync(markup, [new SignatureHelpTestItem("double C.Goo(double x, double y)", string.Empty, string.Empty, currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545118")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545118")] public async Task TestStatic1() { var markup = """ @@ -506,8 +499,7 @@ void Bar(int i) await TestAsync(markup, [new SignatureHelpTestItem("void C.Bar()", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545118")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545118")] public async Task TestStatic2() { var markup = """ @@ -533,8 +525,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void C.Bar(int i)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543117")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543117")] public async Task TestInvocationOnAnonymousType() { var markup = """ @@ -573,8 +564,7 @@ await TestAsync(markup, [ """)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnBaseExpression_ProtectedAccessibility() { var markup = """ @@ -606,8 +596,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnBaseExpression_AbstractBase() { var markup = """ @@ -639,8 +628,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnThisExpression_ProtectedAccessibility() { var markup = """ @@ -667,8 +655,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnThisExpression_ProtectedAccessibility_Overridden() { var markup = """ @@ -700,8 +687,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnThisExpression_ProtectedAccessibility_AbstractBase() { var markup = """ @@ -728,8 +714,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnThisExpression_ProtectedAccessibility_AbstractBase_Overridden() { var markup = """ @@ -761,8 +746,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnBaseExpression_ProtectedInternalAccessibility() { var markup = """ @@ -794,8 +778,7 @@ await TestAsync(markup, [new SignatureHelpTestItem( description: string.Empty)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnBaseMember_ProtectedAccessibility_ThroughType() { var markup = """ @@ -822,8 +805,7 @@ protected override void Goo(int x) await TestAsync(markup, null); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968188")] public async Task TestInvocationOnBaseExpression_PrivateAccessibility() { var markup = """ @@ -874,8 +856,7 @@ void Goo(int someParameter, bool something) #region "Trigger tests" - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/47364")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47364")] public async Task TestInvocationOnTriggerParens_OptionalDefaultStruct() { var markup = """ @@ -1004,8 +985,7 @@ public void TestTriggerCharacters() #region "EditorBrowsable tests" - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_Method_BrowsableStateAlways() { var markup = """ @@ -1038,8 +1018,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync( referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_Method_BrowsableStateNever() { var markup = """ @@ -1071,8 +1050,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync( referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_Method_BrowsableStateAdvanced() { var markup = """ @@ -1113,8 +1091,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, hideAdvancedMembers: false); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_Method_Overloads_OneBrowsableAlways_OneBrowsableNever() { var markup = """ @@ -1152,8 +1129,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_Method_Overloads_BothBrowsableNever() { var markup = """ @@ -1192,8 +1168,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync( referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task OverriddenSymbolsFilteredFromSigHelp() { var markup = """ @@ -1235,8 +1210,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_BrowsableStateAlwaysMethodInBrowsableStateNeverClass() { var markup = """ @@ -1268,8 +1242,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_BrowsableStateAlwaysMethodInBrowsableStateNeverBaseClass() { var markup = """ @@ -1312,8 +1285,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_BrowsableStateNeverMethodsInBaseClass() { var markup = """ @@ -1344,8 +1316,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericTypeCausingMethodSignatureEquality_BothBrowsableAlways() { var markup = """ @@ -1379,8 +1350,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericTypeCausingMethodSignatureEquality_BrowsableMixed1() { var markup = """ @@ -1412,8 +1382,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericTypeCausingMethodSignatureEquality_BrowsableMixed2() { var markup = """ @@ -1445,8 +1414,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericTypeCausingMethodSignatureEquality_BothBrowsableNever() { var markup = """ @@ -1480,8 +1448,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericType2CausingMethodSignatureEquality_BothBrowsableAlways() { var markup = """ @@ -1516,8 +1483,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericType2CausingMethodSignatureEquality_BrowsableMixed() { var markup = """ @@ -1549,8 +1515,7 @@ await TestSignatureHelpInEditorBrowsableContextsAsync(markup: markup, referencedLanguage: LanguageNames.CSharp); } - [Fact] - [WorkItem(7336, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(7336, "DevDiv_Projects/Roslyn")] public async Task EditorBrowsable_GenericType2CausingMethodSignatureEquality_BothBrowsableNever() { var markup = """ @@ -1621,8 +1586,7 @@ async Task> Goo() #endregion - [Fact] - [WorkItem(13849, "DevDiv_Projects/Roslyn")] + [Fact, WorkItem(13849, "DevDiv_Projects/Roslyn")] public async Task TestSpecificity1() { var markup = """ @@ -1647,8 +1611,7 @@ public void M(int t) { } await TestAsync(markup, [new SignatureHelpTestItem("void C.M(int t)", string.Empty, "Real t", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530017")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530017")] public async Task LongSignature() { var markup = """ @@ -1702,8 +1665,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem($"({CSharpFeaturesResources.extension}) void IGoo.Bar()", currentParameterIndex: 0)], sourceCodeKind: SourceCodeKind.Regular); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_PickInt() { var markup = """ @@ -1723,8 +1685,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem($"void Program.M(string s)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_PickInt_ReverseOrder() { var markup = """ @@ -1744,8 +1705,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem($"void Program.M(string s)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_PickSecond() { var markup = """ @@ -1765,8 +1725,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem($"void Program.M(string s)", currentParameterIndex: 0, isSelected: true)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_OtherName_PickIntRemaining() { var markup = """ @@ -1787,8 +1746,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void D.M(string i)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_OtherName_PickIntRemaining_ConversionToD() { var markup = """ @@ -1810,8 +1768,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void D.M(string i)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_OtherName_PickIntRemaining_ReversedOrder() { var markup = """ @@ -1832,8 +1789,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void D.M(string i)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_OtherName_PickStringRemaining() { var markup = """ @@ -1854,8 +1810,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void D.M(string i)", currentParameterIndex: 0, isSelected: true)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/25830")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/25830")] public async Task PickCorrectOverload_RefKind() { var markup = """ @@ -2037,8 +1992,7 @@ void M(int i1, params int i2) { } await TestAsync(source, [new SignatureHelpTestItem("void Program.M(int i1, params int i2)", currentParameterIndex: 1, isSelected: true)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/6713")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/6713")] public async Task PickCorrectOverload_Incomplete_OutOfPositionArgument() { var markup = """ @@ -2180,8 +2134,7 @@ void C.bar() """, currentParameterIndex: 0)], hideAdvancedMembers: false); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] public async Task InstanceAndStaticMethodsShown1() { var markup = """ @@ -2207,8 +2160,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void Goo.Bar(string s)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] public async Task InstanceAndStaticMethodsShown2() { var markup = """ @@ -2234,8 +2186,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void Goo.Bar(string s)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] public async Task InstanceAndStaticMethodsShown3() { var markup = """ @@ -2261,8 +2212,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void Goo.Bar(string s)", currentParameterIndex: 0)]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] public async Task InstanceAndStaticMethodsShown4() { var markup = """ @@ -2285,8 +2235,7 @@ public static void Bar(string s) { } await TestAsync(markup, []); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768697")] public async Task InstanceAndStaticMethodsShown5() { var markup = """ @@ -2309,8 +2258,7 @@ public static void Bar(string s) { } await TestAsync(markup, []); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/33549")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/33549")] public async Task ShowOnlyStaticMethodsForBuildInTypes() { var markup = """ @@ -2329,8 +2277,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("bool string.Equals(string a, string b, System.StringComparison comparisonType)")]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/23133")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/23133")] public async Task ShowOnlyStaticMethodsForNotImportedTypes() { var markup = """ @@ -2354,8 +2301,7 @@ public static void Bar(string s) { } await TestAsync(markup, [new SignatureHelpTestItem("void Test.Goo.Bar(string s)")]); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067933")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1067933")] public async Task InvokedWithNoToken() { var markup = """ @@ -2403,8 +2349,7 @@ void C.Do(int x) """, currentParameterIndex: 0)], hideAdvancedMembers: false); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/699")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/699")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1068424")] public async Task TestGenericParameters1() { @@ -2426,8 +2371,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void C.Goo(T a, U b)", string.Empty)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/699")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/699")] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1068424")] public async Task TestGenericParameters2() { @@ -2449,8 +2393,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("void C.Goo(T a, U b)", string.Empty, string.Empty, currentParameterIndex: 1)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/4144")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4144")] public async Task TestSigHelpIsVisibleOnInaccessibleItem() { var markup = """ @@ -2563,8 +2506,7 @@ await TestAsync(markup, [ new SignatureHelpTestItem("bool Comparer.Equals(string x, string y)", currentParameterIndex: 1, isSelected: true)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/38074")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38074")] [CompilerTrait(CompilerFeature.LocalFunctions)] public async Task TestLocalFunction() { @@ -2582,8 +2524,7 @@ void Local() { } await TestAsync(markup, [new SignatureHelpTestItem("void Local()")]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/38074")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38074")] [CompilerTrait(CompilerFeature.LocalFunctions)] public async Task TestLocalFunctionInStaticMethod() { diff --git a/src/EditorFeatures/CSharpTest/SplitComment/SplitCommentCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/SplitComment/SplitCommentCommandHandlerTests.cs index 94c40b77f78cb..57b9e4ca29a58 100644 --- a/src/EditorFeatures/CSharpTest/SplitComment/SplitCommentCommandHandlerTests.cs +++ b/src/EditorFeatures/CSharpTest/SplitComment/SplitCommentCommandHandlerTests.cs @@ -17,8 +17,7 @@ public class SplitCommentCommandHandlerTests : AbstractSplitCommentCommandHandle protected override EditorTestWorkspace CreateWorkspace(string markup) => EditorTestWorkspace.CreateCSharp(markup); - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestWithSelection() { TestHandled( @@ -43,8 +42,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestWithAllWhitespaceSelection() { TestHandled( @@ -69,8 +67,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestMissingInSlashes() { TestNotHandled( @@ -85,8 +82,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestMissingAtEndOfFile() { TestNotHandled( @@ -99,8 +95,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestMissingBeforeSlashes() { TestNotHandled( @@ -115,8 +110,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestMissingWithMultiSelection() { TestNotHandled( @@ -131,8 +125,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitStartOfComment() { TestHandled( @@ -157,8 +150,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitStartOfQuadComment() { TestHandled( @@ -184,8 +176,7 @@ public static void Main(string[] args) } [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WorkItem("https://github.com/dotnet/roslyn/issues/48547")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/48547")] public void TestSplitMiddleOfQuadComment() { TestNotHandled( @@ -200,8 +191,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/48547")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/48547")] public void TestSplitWithCommentAfterwards1() { TestNotHandled( @@ -216,8 +206,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/48547")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/48547")] public void TestSplitWithCommentAfterwards2() { TestNotHandled( @@ -232,8 +221,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/48547")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/48547")] public void TestSplitWithCommentAfterwards3() { TestNotHandled( @@ -248,8 +236,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/48547")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/48547")] public void TestSplitWithCommentAfterwards4() { TestNotHandled( @@ -264,8 +251,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitStartOfCommentWithLeadingSpace1() { TestHandled( @@ -290,8 +276,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitStartOfCommentWithLeadingSpace2() { TestHandled( @@ -373,8 +358,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitMiddleOfComment() { TestHandled( @@ -399,8 +383,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitEndOfComment() { TestNotHandled( @@ -415,8 +398,7 @@ public static void Main(string[] args) """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitCommentEndOfLine1() { TestHandled( @@ -439,8 +421,7 @@ public static void Main(string[] args) // Test """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestSplitCommentEndOfLine2() { TestHandled( @@ -463,8 +444,7 @@ public static void Main(string[] args) // Test """); } - [WorkItem("https://github.com/dotnet/roslyn/issues/38516")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/38516")] public void TestUseTabs() { TestHandled( diff --git a/src/EditorFeatures/CSharpTest/SplitStringLiteral/SplitStringLiteralCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/SplitStringLiteral/SplitStringLiteralCommandHandlerTests.cs index aaaeb3cd0dd75..40a0ab37f2cd7 100644 --- a/src/EditorFeatures/CSharpTest/SplitStringLiteral/SplitStringLiteralCommandHandlerTests.cs +++ b/src/EditorFeatures/CSharpTest/SplitStringLiteral/SplitStringLiteralCommandHandlerTests.cs @@ -724,8 +724,7 @@ void M() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20258")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20258")] public void TestBeforeEndQuote1() { // Do not verifyUndo because of https://github.com/dotnet/roslyn/issues/28033 @@ -761,8 +760,7 @@ static void Main(string[] args) verifyUndo: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20258")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20258")] public void TestBeforeEndQuote2() { // Do not verifyUndo because of https://github.com/dotnet/roslyn/issues/28033 @@ -798,8 +796,7 @@ static void Main(string[] args) verifyUndo: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20258")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20258")] public void TestBeforeEndQuote3() { // Do not verifyUndo because of https://github.com/dotnet/roslyn/issues/28033 @@ -835,8 +832,7 @@ static void Main(string[] args) verifyUndo: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20258")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20258")] public void TestBeforeEndQuote4() { // Do not verifyUndo because of https://github.com/dotnet/roslyn/issues/28033 @@ -872,8 +868,7 @@ static void Main(string[] args) verifyUndo: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20258")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20258")] public void TestBeforeEndQuote5() { // Do not verifyUndo because of https://github.com/dotnet/roslyn/issues/28033 @@ -909,8 +904,7 @@ static void Main(string[] args) verifyUndo: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/20258")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20258")] public void TestBeforeEndQuote6() { // Do not verifyUndo because of https://github.com/dotnet/roslyn/issues/28033 @@ -946,8 +940,7 @@ static void Main(string[] args) verifyUndo: false); } - [WorkItem("https://github.com/dotnet/roslyn/issues/39040")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/39040")] public void TestMultiCaretSingleLine() { TestHandled( @@ -969,8 +962,7 @@ void M() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/39040")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/39040")] public void TestMultiCaretMultiLines() { TestHandled( @@ -997,8 +989,7 @@ void M() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/39040")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/39040")] public void TestMultiCaretInterpolatedString() { TestHandled( @@ -1026,8 +1017,7 @@ void M() }"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/40277")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/40277")] public void TestInStringWithKeepTabsEnabled1() { TestHandled( @@ -1049,8 +1039,7 @@ void M() useTabs: true); } - [WorkItem("https://github.com/dotnet/roslyn/issues/40277")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/40277")] public void TestInStringWithKeepTabsEnabled2() { TestHandled( diff --git a/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs b/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs index 569f3f94f9a93..0777944e817fa 100644 --- a/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs +++ b/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs @@ -275,7 +275,7 @@ public async Task TestNoErrorsAfterDocumentRemoved() spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); // And we should have no errors for this document. - Assert.True(spans.Count == 0); + Assert.Empty(spans); } [WpfFact] @@ -308,7 +308,7 @@ public async Task TestNoErrorsAfterProjectRemoved() spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); // And we should have no errors for this document. - Assert.True(spans.Count == 0); + Assert.Empty(spans); } private static readonly TestComposition s_mockComposition = EditorTestCompositions.EditorFeatures diff --git a/src/EditorFeatures/CSharpTest/Structure/CollectionExpressionStructureTests.cs b/src/EditorFeatures/CSharpTest/Structure/CollectionExpressionStructureTests.cs new file mode 100644 index 0000000000000..8533be3d654c5 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/Structure/CollectionExpressionStructureTests.cs @@ -0,0 +1,89 @@ +// 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. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Structure; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Structure; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Structure; + +[Trait(Traits.Feature, Traits.Features.Outlining)] +public class CollectionExpressionStructureTests : AbstractCSharpSyntaxNodeStructureTests +{ + internal override AbstractSyntaxStructureProvider CreateProvider() + => new CollectionExpressionStructureProvider(); + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71932")] + public async Task TestOuterCollectionExpression() + { + await VerifyBlockSpansAsync( + """ + class C + { + void M() + { + int[] a ={|hint:{|textspan: $$[ + 1, + 2, + 3 + ]|}|}; + } + } + """, + Region("textspan", "hint", CSharpStructureHelpers.Ellipsis, autoCollapse: false)); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71932")] + public async Task TestInnerCollectionExpressionWithoutComma() + { + await VerifyBlockSpansAsync( + """ + class C + { + void M() + { + List> b = + [ + [1], + [2, 3], + {|hint:{|textspan:$$[ + 3, 5, 6 + ]|}|} + ]; + } + } + """, + Region("textspan", "hint", CSharpStructureHelpers.Ellipsis, autoCollapse: false)); + } + + [Fact] + [WorkItem("https://github.com/dotnet/roslyn/issues/71932")] + public async Task TestInnerCollectionExpressionWithComma() + { + await VerifyBlockSpansAsync( + """ + class C + { + void M() + { + List> c = + [ + [1], + [2, 3], + {|hint:{|textspan:$$[ + 3, 5, 6 + ],|}|} + ]; + } + } + """, + Region("textspan", "hint", CSharpStructureHelpers.Ellipsis, autoCollapse: false)); + } +} diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/InKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/InKeywordRecommenderTests.cs index 1a52f7227852c..76cf60203ed7e 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/InKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/InKeywordRecommenderTests.cs @@ -131,8 +131,7 @@ join z in $$ """)); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] public async Task TestNotAfterJoinPredefinedType() { await VerifyAbsenceAsync( @@ -147,8 +146,7 @@ join int $$ """); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] public async Task TestNotAfterJoinType() { await VerifyAbsenceAsync( @@ -306,8 +304,7 @@ await VerifyKeywordAsync(AddInsideMethod( @"var q2 = from x $$ ((IEnumerable)src))")); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] public async Task TestNotAfterFromPredefinedType() { await VerifyAbsenceAsync( @@ -321,8 +318,7 @@ void M() """); } - [Fact] - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544158")] public async Task TestNotAfterFromType() { await VerifyAbsenceAsync( @@ -531,8 +527,7 @@ public C(object arg1) : this(arg1, $$ } [CompilerTrait(CompilerFeature.ReadOnlyReferences)] - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/24079")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/24079")] public async Task TestInAsParameterModifierInConversionOperators() { await VerifyKeywordAsync(""" @@ -544,8 +539,7 @@ public static explicit operator double($$) { } } [CompilerTrait(CompilerFeature.ReadOnlyReferences)] - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/24079")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/24079")] public async Task TestInAsParameterModifierInBinaryOperators() { await VerifyKeywordAsync(""" @@ -672,8 +666,7 @@ static void Extension($$ """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/30339")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/30339")] public async Task TestExtensionMethods_FirstParameter_AfterThisKeyword() { await VerifyKeywordAsync( diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs index 427467dbfab91..059a0032eafe7 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ReadOnlyKeywordRecommenderTests.cs @@ -468,8 +468,7 @@ public async Task TestInRefStruct() public async Task TestInRefStructBeforeRef() => await VerifyKeywordAsync(@"$$ ref struct { }"); - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/44423")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44423")] public async Task TestAfterNew() => await VerifyAbsenceAsync(@"new $$"); diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.cs.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.cs.xlf index 5d435e8efb94e..74efd3bc19924 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.cs.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.cs.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + Generování návrhů… @@ -54,7 +54,7 @@ Reset the execution environment to the initial state and keep history, with the option to switch the runtime of the host process. - Obnovte spouštěcí prostředí do počátečního stavu a uložte historii s možností přepnout modul runtime hostitelského procesu. + Resetujte spouštěcí prostředí do počátečního stavu a zachovejte historii s možností přepnout modul runtime hostitelského procesu. diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.fr.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.fr.xlf index 69f7cd1f71c13..95d215d86b752 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.fr.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.fr.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + Génération en cours de suggestions... diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.ja.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.ja.xlf index e4e34ff935ae6..d146d32c45dea 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.ja.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.ja.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + 候補を生成しています... diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pl.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pl.xlf index 0cd527d683dae..50fb8f133ddff 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pl.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pl.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + Generowanie sugestii... @@ -54,7 +54,7 @@ Reset the execution environment to the initial state and keep history, with the option to switch the runtime of the host process. - Zresetuj środowisko wykonywania do stanu początkowego i zachowaj historię, korzystając z opcji przełączenia środowiska uruchomieniowego procesu hosta. + Zresetuj środowisko wykonawcze do stanu początkowego i zachowaj historię z opcją przełączenia środowiska uruchomieniowego procesu hosta. diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pt-BR.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pt-BR.xlf index 25412f5fcf06e..079cdb4a2f89a 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pt-BR.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.pt-BR.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + Gerando sugestões... @@ -54,7 +54,7 @@ Reset the execution environment to the initial state and keep history, with the option to switch the runtime of the host process. - Redefina o ambiente de execução para o estado inicial e mantenha o histórico, com a opção de alternar o tempo de execução do processo de host. + Redefine o ambiente de execução para o estado inicial e mantém o histórico, com a opção de mudar o runtime do processo do host. diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.tr.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.tr.xlf index c8bea08216e3c..d46c18482e002 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.tr.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.tr.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + Öneriler oluşturuluyor... @@ -54,7 +54,7 @@ Reset the execution environment to the initial state and keep history, with the option to switch the runtime of the host process. - Yürütme ortamını başlangıç durumuna sıfırlayın ve ana bilgisayar işleminin çalışma zamanını değiştirme seçeneğiyle geçmişi tut. + Ana işleminin çalışma zamanını değiştirme seçeneğini belirleyerek yürütme ortamını başlangıç durumuna sıfırlayın ve geçmişi tutun. diff --git a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.zh-Hant.xlf b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.zh-Hant.xlf index 9cb0cd8d67448..865b373a6b6c0 100644 --- a/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.zh-Hant.xlf +++ b/src/EditorFeatures/Core.Wpf/xlf/EditorFeaturesWpfResources.zh-Hant.xlf @@ -34,7 +34,7 @@ Generating suggestions... - Generating suggestions... + 正在產生建議... @@ -54,7 +54,7 @@ Reset the execution environment to the initial state and keep history, with the option to switch the runtime of the host process. - 使用選項切換主機處理常式的執行時間,將執行環境重設為初始狀態並保留歷程記錄。 + 使用切換主機處理序的執行階段選項,將執行環境重設為初始狀態並保留歷程記錄。 diff --git a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs index 24b0a84522461..49ea250a76db9 100644 --- a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs +++ b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs @@ -101,6 +101,12 @@ protected override async Task ProduceTagsAsync( if (document == null) return; + // The LSP client will handle producing tags when running under the LSP editor. + // Our tagger implementation should return nothing to prevent conflicts. + var workspaceContextService = document.Project.Solution.Services.GetRequiredService(); + if (workspaceContextService.IsInLspEditorContext()) + return; + var service = document.GetLanguageService(); if (service == null) return; diff --git a/src/EditorFeatures/Core/IntelliSense/ModelComputation.cs b/src/EditorFeatures/Core/IntelliSense/ModelComputation.cs index 34ad60a6c31cd..7a8e5c4056cf4 100644 --- a/src/EditorFeatures/Core/IntelliSense/ModelComputation.cs +++ b/src/EditorFeatures/Core/IntelliSense/ModelComputation.cs @@ -153,7 +153,7 @@ public void ChainTaskAndNotifyControllerWhenFinished( // issue the notification, see if we're still at the end of the chain. If we're not, // then we don't need to notify as a later task will do so. _notifyControllerTask = Task.Factory.ContinueWhenAll( - new[] { _notifyControllerTask, nextTask }, + [_notifyControllerTask, nextTask], async tasks => { await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true, _stopCancellationToken); diff --git a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs index bea2259bffb48..d083c40829563 100644 --- a/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs +++ b/src/EditorFeatures/Core/LanguageServer/AlwaysActivateInProcLanguageClient.cs @@ -71,30 +71,33 @@ public override ServerCapabilities GetCapabilities(ClientCapabilities clientCapa if (isPullDiagnostics) { serverCapabilities.SupportsDiagnosticRequests = true; - serverCapabilities.MultipleContextSupportProvider = new VSInternalMultipleContextFeatures { SupportsMultipleContextsDiagnostics = true }; serverCapabilities.DiagnosticProvider ??= new(); - serverCapabilities.DiagnosticProvider.DiagnosticKinds = - [ - // Support a specialized requests dedicated to task-list items. This way the client can ask just - // for these, independently of other diagnostics. They can also throttle themselves to not ask if - // the task list would not be visible. - new(PullDiagnosticCategories.Task), - // Dedicated request for workspace-diagnostics only. We will only respond to these if FSA is on. - new(PullDiagnosticCategories.WorkspaceDocumentsAndProject), - // Fine-grained diagnostics requests. Importantly, this separates out syntactic vs semantic - // requests, allowing the former to quickly reach the user without blocking on the latter. In a - // similar vein, compiler diagnostics are explicitly distinct from analyzer-diagnostics, allowing - // the former to appear as soon as possible as they are much more critical for the user and should - // not be delayed by a slow analyzer. - new(PullDiagnosticCategories.DocumentCompilerSyntax), - new(PullDiagnosticCategories.DocumentCompilerSemantic), - new(PullDiagnosticCategories.DocumentAnalyzerSyntax), - new(PullDiagnosticCategories.DocumentAnalyzerSemantic), - ]; - serverCapabilities.DiagnosticProvider.BuildOnlyDiagnosticIds = _buildOnlyDiagnostics - .SelectMany(lazy => lazy.Metadata.BuildOnlyDiagnostics) - .Distinct() - .ToArray(); + serverCapabilities.DiagnosticProvider = serverCapabilities.DiagnosticProvider with + { + SupportsMultipleContextsDiagnostics = true, + DiagnosticKinds = + [ + // Support a specialized requests dedicated to task-list items. This way the client can ask just + // for these, independently of other diagnostics. They can also throttle themselves to not ask if + // the task list would not be visible. + new(PullDiagnosticCategories.Task), + // Dedicated request for workspace-diagnostics only. We will only respond to these if FSA is on. + new(PullDiagnosticCategories.WorkspaceDocumentsAndProject), + // Fine-grained diagnostics requests. Importantly, this separates out syntactic vs semantic + // requests, allowing the former to quickly reach the user without blocking on the latter. In a + // similar vein, compiler diagnostics are explicitly distinct from analyzer-diagnostics, allowing + // the former to appear as soon as possible as they are much more critical for the user and should + // not be delayed by a slow analyzer. + new(PullDiagnosticCategories.DocumentCompilerSyntax), + new(PullDiagnosticCategories.DocumentCompilerSemantic), + new(PullDiagnosticCategories.DocumentAnalyzerSyntax), + new(PullDiagnosticCategories.DocumentAnalyzerSemantic), + ], + BuildOnlyDiagnosticIds = _buildOnlyDiagnostics + .SelectMany(lazy => lazy.Metadata.BuildOnlyDiagnostics) + .Distinct() + .ToArray(), + }; } // This capability is always enabled as we provide cntrl+Q VS search only via LSP in ever scenario. diff --git a/src/EditorFeatures/Core/Preview/AbstractPreviewFactoryService.cs b/src/EditorFeatures/Core/Preview/AbstractPreviewFactoryService.cs index f23f03bebb6b3..3eefa837cd9c4 100644 --- a/src/EditorFeatures/Core/Preview/AbstractPreviewFactoryService.cs +++ b/src/EditorFeatures/Core/Preview/AbstractPreviewFactoryService.cs @@ -468,10 +468,23 @@ public Task> CreateRemovedAnalyzerCo // Create PreviewWorkspaces around the buffers to be displayed on the left and right // so that all IDE services (colorizer, squiggles etc.) light up in these buffers. - using var leftWorkspace = new ReferenceCountedDisposable(new PreviewWorkspace(oldDocument.Project.Solution)); + // + // Performance: Replace related documents to oldBuffer and newBuffer in these workspaces with the + // relating SourceText. This prevents cascading forks as taggers call to + // GetOpenTextDocumentInCurrentContextWithChanges would eventually wind up + // calling Solution.WithDocumentText using the related ids. + var leftSolution = oldDocument.Project.Solution; + var allLeftIds = leftSolution.GetRelatedDocumentIds(oldDocument.Id); + leftSolution = leftSolution.WithDocumentText(allLeftIds, oldBuffer.AsTextContainer().CurrentText, PreservationMode.PreserveIdentity); + + using var leftWorkspace = new ReferenceCountedDisposable(new PreviewWorkspace(leftSolution)); leftWorkspace.Target.OpenDocument(oldDocument.Id, oldBuffer.AsTextContainer()); - using var rightWorkspace = new ReferenceCountedDisposable(new PreviewWorkspace(newDocument.Project.Solution)); + var rightSolution = newDocument.Project.Solution; + var allRightIds = rightSolution.GetRelatedDocumentIds(newDocument.Id); + rightSolution = rightSolution.WithDocumentText(allRightIds, newBuffer.AsTextContainer().CurrentText, PreservationMode.PreserveIdentity); + + using var rightWorkspace = new ReferenceCountedDisposable(new PreviewWorkspace(rightSolution)); rightWorkspace.Target.OpenDocument(newDocument.Id, newBuffer.AsTextContainer()); #pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task (containing method uses JTF) diff --git a/src/EditorFeatures/Core/Shared/Extensions/ITextBufferExtensions.cs b/src/EditorFeatures/Core/Shared/Extensions/ITextBufferExtensions.cs index 8b3106f59f2cb..4d6820845a389 100644 --- a/src/EditorFeatures/Core/Shared/Extensions/ITextBufferExtensions.cs +++ b/src/EditorFeatures/Core/Shared/Extensions/ITextBufferExtensions.cs @@ -66,7 +66,7 @@ public static ITextSnapshot ApplyChange(this ITextBuffer buffer, TextChange chan { if (buffer.Properties.TryGetProperty(typeof(IContainedDocument), out var containedDocument)) { - return containedDocument.ApplyChanges(new[] { change }); + return containedDocument.ApplyChanges([change]); } using var edit = buffer.CreateEdit(EditOptions.DefaultMinimalChange, reiteratedVersionNumber: null, editTag: null); diff --git a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs index d50744a4ff7ae..39e161bffbaee 100644 --- a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs +++ b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs @@ -985,8 +985,8 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) #pragma warning disable RS0034 // Exported parts should be marked with 'ImportingConstructorAttribute' [ExportCodeFixProvider( LanguageNames.CSharp, - DocumentKinds = new[] { nameof(TextDocumentKind.AdditionalDocument) }, - DocumentExtensions = new[] { ".txt" })] + DocumentKinds = [nameof(TextDocumentKind.AdditionalDocument)], + DocumentExtensions = [".txt"])] [Shared] internal sealed class AdditionalFileFixerWithDocumentKindsAndExtensions : AbstractAdditionalFileCodeFixProvider { @@ -995,7 +995,7 @@ public AdditionalFileFixerWithDocumentKindsAndExtensions() : base(nameof(Additio [ExportCodeFixProvider( LanguageNames.CSharp, - DocumentKinds = new[] { nameof(TextDocumentKind.AdditionalDocument) })] + DocumentKinds = [nameof(TextDocumentKind.AdditionalDocument)])] [Shared] internal sealed class AdditionalFileFixerWithDocumentKinds : AbstractAdditionalFileCodeFixProvider { @@ -1004,7 +1004,7 @@ public AdditionalFileFixerWithDocumentKinds() : base(nameof(AdditionalFileFixerW [ExportCodeFixProvider( LanguageNames.CSharp, - DocumentExtensions = new[] { ".txt" })] + DocumentExtensions = [".txt"])] [Shared] internal sealed class AdditionalFileFixerWithDocumentExtensions : AbstractAdditionalFileCodeFixProvider { diff --git a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs index 6b13cf99b607b..18c44bd4832e1 100644 --- a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs +++ b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs @@ -529,7 +529,7 @@ public async Task StartDebuggingSession_CapturingDocuments(bool captureAllDocume sourceFileB.WriteAllText(sourceB2, encodingB); // prepare workspace as if it was loaded from project files: - using var _ = CreateWorkspace(out var solution, out var service, new[] { typeof(NoCompilationLanguageService) }); + using var _ = CreateWorkspace(out var solution, out var service, [typeof(NoCompilationLanguageService)]); var projectPId = ProjectId.CreateNewId(); solution = solution @@ -684,7 +684,7 @@ public async Task DifferentDocumentWithSameContent() [CombinatorialData] public async Task ProjectThatDoesNotSupportEnC(bool breakMode) { - using var _ = CreateWorkspace(out var solution, out var service, new[] { typeof(NoCompilationLanguageService) }); + using var _ = CreateWorkspace(out var solution, out var service, [typeof(NoCompilationLanguageService)]); var project = solution.AddProject("dummy_proj", "dummy_proj", NoCompilationConstants.LanguageName); var document = project.AddDocument("test", CreateText("dummy1")); solution = document.Project.Solution; @@ -2000,7 +2000,7 @@ public async Task HasChanges_Documents(DocumentKind documentKind) await EditSession.GetChangedDocumentsAsync(oldSolution.GetProject(projectId), solution.GetProject(projectId), CancellationToken.None).ToImmutableArrayAsync(CancellationToken.None)); await EditSession.PopulateChangedAndAddedDocumentsAsync(oldSolution.GetProject(projectId), solution.GetProject(projectId), changedOrAddedDocuments, CancellationToken.None); - AssertEx.Equal(documentKind == DocumentKind.Source ? new[] { documentId, generatedDocumentId } : new[] { generatedDocumentId }, changedOrAddedDocuments.Select(d => d.Id)); + AssertEx.Equal(documentKind == DocumentKind.Source ? [documentId, generatedDocumentId] : [generatedDocumentId], changedOrAddedDocuments.Select(d => d.Id)); Assert.Equal(1, generatorExecutionCount); @@ -2048,11 +2048,11 @@ public async Task HasChanges_Documents(DocumentKind documentKind) Assert.True(await EditSession.HasChangesAsync(oldSolution, solution, CancellationToken.None)); Assert.True(await EditSession.HasChangesAsync(oldSolution, solution, pathX, CancellationToken.None)); - AssertEx.Equal(documentKind == DocumentKind.Source ? new[] { documentId, generatedDocumentId } : new[] { generatedDocumentId }, + AssertEx.Equal(documentKind == DocumentKind.Source ? [documentId, generatedDocumentId] : [generatedDocumentId], await EditSession.GetChangedDocumentsAsync(oldSolution.GetProject(projectId), solution.GetProject(projectId), CancellationToken.None).ToImmutableArrayAsync(CancellationToken.None)); await EditSession.PopulateChangedAndAddedDocumentsAsync(oldSolution.GetProject(projectId), solution.GetProject(projectId), changedOrAddedDocuments, CancellationToken.None); - AssertEx.Equal(documentKind == DocumentKind.Source ? new[] { documentId, generatedDocumentId } : new[] { generatedDocumentId }, changedOrAddedDocuments.Select(d => d.Id)); + AssertEx.Equal(documentKind == DocumentKind.Source ? [documentId, generatedDocumentId] : [generatedDocumentId], changedOrAddedDocuments.Select(d => d.Id)); Assert.Equal(1, generatorExecutionCount); @@ -3749,8 +3749,8 @@ public async Task ActiveStatements_LinkedDocuments() var debugInfos = GetActiveStatementDebugInfosCSharp( markedSources, - methodRowIds: new[] { 1, 2, 1 }, - modules: new[] { module4, module2, module1 }); + methodRowIds: [1, 2, 1], + modules: [module4, module2, module1]); // Project1: Test1.cs, Test2.cs // Project2: Test1.cs (link from P1) @@ -3867,12 +3867,12 @@ static void M() var debugInfos = GetActiveStatementDebugInfosCSharp( markedSources, - methodRowIds: new[] { 1 }, - ilOffsets: new[] { 1 }, - flags: new[] - { + methodRowIds: [1], + ilOffsets: [1], + flags: + [ ActiveStatementFlags.LeafFrame | ActiveStatementFlags.MethodUpToDate - }); + ]); using var _ = CreateWorkspace(out var solution, out var service); solution = AddDefaultTestProject(solution, SourceMarkers.Clear(markedSources)); @@ -3967,13 +3967,13 @@ void F() EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( new[] { GetGeneratedCodeFromMarkedSource(markedSource1) }, filePaths: new[] { generatedDocument1.FilePath }, - modules: new[] { moduleId }, - methodRowIds: new[] { 1 }, - methodVersions: new[] { 1 }, - flags: new[] - { + modules: [moduleId], + methodRowIds: [1], + methodVersions: [1], + flags: + [ ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.LeafFrame - })); + ])); // change the source (valid edit) solution = solution.WithDocumentText(document1.Id, CreateText(source2)); @@ -4049,13 +4049,13 @@ int F() EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( new[] { markedSource1 }, - modules: new[] { moduleId }, - methodRowIds: new[] { 1 }, - methodVersions: new[] { 1 }, - flags: new[] - { + modules: [moduleId], + methodRowIds: [1], + methodVersions: [1], + flags: + [ ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.LeafFrame - })); + ])); // change the source (rude edit) solution = solution.WithDocumentText(document.Id, CreateText(source2)); @@ -4135,14 +4135,14 @@ static void F() EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( new[] { markedSourceV1 }, - modules: new[] { moduleId, moduleId }, - methodRowIds: new[] { 2, 3 }, - methodVersions: new[] { 1, 1 }, - flags: new[] - { + modules: [moduleId, moduleId], + methodRowIds: [2, 3], + methodVersions: [1, 1], + flags: + [ ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.LeafFrame, // G ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.NonLeafFrame, // F - })); + ])); solution = solution.WithDocumentText(documentId, CreateText(SourceMarkers.Clear(markedSourceV2))); @@ -4185,14 +4185,14 @@ static void F() EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( new[] { markedSourceV1 }, // matches F v1 - modules: new[] { moduleId, moduleId }, - methodRowIds: new[] { 2, 3 }, - methodVersions: new[] { 1, 1 }, // frame F v1 is still executing (G has not returned) - flags: new[] - { + modules: [moduleId, moduleId], + methodRowIds: [2, 3], + methodVersions: [1, 1], // frame F v1 is still executing (G has not returned) + flags: + [ ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.LeafFrame, // G ActiveStatementFlags.Stale | ActiveStatementFlags.NonLeafFrame, // F - not up-to-date anymore and since F v1 is followed by F v3 (hot-reload) it is now stale - })); + ])); var spans = (await debuggingSession.GetBaseActiveStatementSpansAsync(solution, ImmutableArray.Create(documentId), CancellationToken.None)).Single(); AssertEx.Equal(new[] @@ -4283,14 +4283,14 @@ static void F() EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( new[] { markedSource1 }, - modules: new[] { moduleId, moduleId }, - methodRowIds: new[] { 2, 3 }, - methodVersions: new[] { 1, 1 }, - flags: new[] - { + modules: [moduleId, moduleId], + methodRowIds: [2, 3], + methodVersions: [1, 1], + flags: + [ ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.LeafFrame, // G ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.NonLeafFrame, // F - })); + ])); // check that the active statement is mapped correctly to snapshot v2: var expectedSpanG1 = new LinePositionSpan(new LinePosition(3, 41), new LinePosition(3, 42)); @@ -4393,14 +4393,14 @@ static void F() EnterBreakState(debuggingSession, GetActiveStatementDebugInfosCSharp( new[] { markedSource1 }, - modules: new[] { moduleId, moduleId }, - methodRowIds: new[] { 2, 3 }, - methodVersions: new[] { 1, 1 }, // frame F v1 is still executing (G has not returned) - flags: new[] - { + modules: [moduleId, moduleId], + methodRowIds: [2, 3], + methodVersions: [1, 1], // frame F v1 is still executing (G has not returned) + flags: + [ ActiveStatementFlags.MethodUpToDate | ActiveStatementFlags.LeafFrame, // G ActiveStatementFlags.NonLeafFrame, // F - })); + ])); // check that the active statement is mapped correctly to snapshot v2: var expectedSpanG1 = new LinePositionSpan(new LinePosition(3, 41), new LinePosition(3, 42)); diff --git a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs index f59e1e145eb5e..f9e9bdb7deb84 100644 --- a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs +++ b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs @@ -99,8 +99,7 @@ public void TestPreviewProjectChanges() Assert.Equal(0, previewWorkspace.CurrentSolution.Projects.First().DocumentIds.Count); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/923121")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/923121")] public void TestPreviewOpenCloseFile() { using var previewWorkspace = new PreviewWorkspace(); @@ -229,8 +228,7 @@ public async Task TestPreviewDiagnosticTaggerInPreviewPane() Assert.Equal(0, rightSpans.Count); } - [WorkItem("https://github.com/dotnet/roslyn/issues/28639")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/28639")] public void TestPreviewWorkspaceDoesNotLeakSolution() { // Verify that analyzer execution doesn't leak solution instances from the preview workspace. @@ -253,8 +251,7 @@ public void TestPreviewWorkspaceDoesNotLeakSolution() solutionObjectReference.AssertReleased(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/pull/67142")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/pull/67142")] public void TestPreviewWorkspaceDoesNotLeakItself() { var composition = EditorTestCompositions.EditorFeatures; diff --git a/src/EditorFeatures/Test/Tagging/TagSpanIntervalTreeTests.cs b/src/EditorFeatures/Test/Tagging/TagSpanIntervalTreeTests.cs index 8395563dddaa9..25935fcd5dfad 100644 --- a/src/EditorFeatures/Test/Tagging/TagSpanIntervalTreeTests.cs +++ b/src/EditorFeatures/Test/Tagging/TagSpanIntervalTreeTests.cs @@ -139,7 +139,7 @@ public void TestEmptySpanIntersects1() { var tree = CreateTree("goo", new Span(0, 0)); var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(0, 0))); - Assert.True(spans.Count == 1); + Assert.Single(spans); } [Fact] @@ -147,7 +147,7 @@ public void TestEmptySpanIntersects2() { var tree = CreateTree("goo", new Span(0, 0)); var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(0, "goo".Length))); - Assert.True(spans.Count == 1); + Assert.Single(spans); } [Fact] @@ -155,7 +155,7 @@ public void TestEmptySpanIntersects3() { var tree = CreateTree("goo", new Span(1, 0)); var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(0, 1))); - Assert.True(spans.Count == 1); + Assert.Single(spans); } [Fact] @@ -163,7 +163,7 @@ public void TestEmptySpanIntersects4() { var tree = CreateTree("goo", new Span(1, 0)); var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(1, 0))); - Assert.True(spans.Count == 1); + Assert.Single(spans); } [Fact] @@ -171,7 +171,7 @@ public void TestEmptySpanIntersects5() { var tree = CreateTree("goo", new Span(1, 0)); var spans = tree.GetIntersectingSpans(new SnapshotSpan(tree.Buffer.CurrentSnapshot, new Span(1, 1))); - Assert.True(spans.Count == 1); + Assert.Single(spans); } } } diff --git a/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs b/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs index be4439abf337f..18b7291a081c9 100644 --- a/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs +++ b/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs @@ -459,7 +459,7 @@ private static ImmutableArray BreakIntoWordParts(string identifier) if (match == null) { - Assert.True(spans.Length == 0); + Assert.Empty(spans); } else { @@ -478,7 +478,7 @@ private static IEnumerable TryMatchMultiWordPattern(string candida if (matches.Count == 0) { - Assert.True(expectedSpans.Length == 0); + Assert.Empty(expectedSpans); return null; } else diff --git a/src/EditorFeatures/Test2/CodeDefinitionWindow/CSharpCodeDefinitionWindowTests.vb b/src/EditorFeatures/Test2/CodeDefinitionWindow/CSharpCodeDefinitionWindowTests.vb index 43ddb006e5dd2..a4dd9670fc9dc 100644 --- a/src/EditorFeatures/Test2/CodeDefinitionWindow/CSharpCodeDefinitionWindowTests.vb +++ b/src/EditorFeatures/Test2/CodeDefinitionWindow/CSharpCodeDefinitionWindowTests.vb @@ -95,6 +95,29 @@ class C End Function + + valueTuple1;", "System.ValueTuple")> + valueTuple2;", "(int, int)")> + valueTuple3;", "(int, int, int)")> + valueTuple4;", "(int, int, int, int)")> + valueTuple5;", "(int, int, int, int, int)")> + valueTuple6;", "(int, int, int, int, int, int)")> + valueTuple7;", "(int, int, int, int, int, int, int)")> + valueTuple8;", "System.ValueTuple")> + Public Async Function ToValueTupleMetadataAsSource(expression As String, expectedDisplayName As String) As Task + Dim code As String = $"using System; +class C +{{ + void M() + {{ + $${expression} valueTuple; + }} +}}" + + Await VerifyContextLocationInMetadataAsSource(code, expectedDisplayName, "ValueTuple.cs") + + End Function + Protected Overrides Function CreateWorkspace(code As String, testComposition As TestComposition) As EditorTestWorkspace Return EditorTestWorkspace.CreateCSharp(code, composition:=testComposition) End Function diff --git a/src/EditorFeatures/Test2/GoToDefinition/CSharpGoToDefinitionTests.vb b/src/EditorFeatures/Test2/GoToDefinition/CSharpGoToDefinitionTests.vb index f0f27b39ab3c8..5f09f4a3b8077 100644 --- a/src/EditorFeatures/Test2/GoToDefinition/CSharpGoToDefinitionTests.vb +++ b/src/EditorFeatures/Test2/GoToDefinition/CSharpGoToDefinitionTests.vb @@ -1224,6 +1224,36 @@ namespace System Await TestAsync(workspace, expectedResult:=False) End Function + + + valueTuple1;")> + valueTuple2;")> + valueTuple3;")> + valueTuple4;")> + valueTuple5;")> + valueTuple6;")> + valueTuple7;")> + valueTuple8;")> + Public Async Function TestCSharpGotoDefinitionWithValueTuple(expression As String) As Task + Dim workspace = + + + + using System; + + class C + { + void M() + { + $$<%= expression %> + } + } + + + + + Await TestAsync(workspace) + End Function #End Region #Region "CSharp Venus Tests" diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb index e3b20566856c0..7c5a001665e27 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb @@ -915,7 +915,7 @@ $$ End Using End Function - + Public Async Function TestDeletingWholeWordResetCompletionToTheDefaultItem(showCompletionInArgumentLists As Boolean) As Task Using state = TestStateFactory.CreateCSharpTestState( diff --git a/src/EditorFeatures/Test2/Peek/PeekTests.vb b/src/EditorFeatures/Test2/Peek/PeekTests.vb index c2d372d863ea0..52b88f3db2613 100644 --- a/src/EditorFeatures/Test2/Peek/PeekTests.vb +++ b/src/EditorFeatures/Test2/Peek/PeekTests.vb @@ -252,6 +252,42 @@ public partial class D End Using End Sub + + valueTuple1;")> + valueTuple2;")> + valueTuple3;")> + valueTuple4;")> + valueTuple5;")> + valueTuple6;")> + valueTuple7;")> + valueTuple8;")> + Public Sub TestPeekDefinitionWithValueType(expression As String) + Dim workspace = + + + + using System; + + class C + { + void M() + { + $$<%= expression %> + } + } + + + + + Using testWorkspace = CreateTestWorkspace(workspace) + Dim result = GetPeekResultCollection(workspace) + + Assert.Equal(1, result.Items.Count) + Assert.Equal($"ValueTuple [{FeaturesResources.from_metadata}]", result(0).DisplayInfo.Label) + Assert.Equal($"ValueTuple [{FeaturesResources.from_metadata}]", result(0).DisplayInfo.Title) + End Using + End Sub + Private Shared Function CreateTestWorkspace(element As XElement) As EditorTestWorkspace Return EditorTestWorkspace.Create(element, composition:=EditorTestCompositions.EditorFeaturesWpf) End Function diff --git a/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs b/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs index 8fff36aea5d64..f5c78cdd823f1 100644 --- a/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs +++ b/src/EditorFeatures/TestUtilities/BraceHighlighting/MultiCharacterBraceHighlightingTests.cs @@ -88,168 +88,147 @@ private class TestBraceMatchingService : IBraceMatchingService } } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotOnBrace() { await TestBraceHighlightingAsync( "$$ <@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestOnLeftOfStartBrace() { await TestBraceHighlightingAsync( "$$[|<@|] [|@>|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestInsideStartBrace() { await TestBraceHighlightingAsync( "[|<$$@|] [|@>|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotOnRightOfStartBrace() { await TestBraceHighlightingAsync( "<@$$ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotOnLeftOfCloseBrace() { await TestBraceHighlightingAsync( "<@ $$@>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestInsideCloseBrace() { await TestBraceHighlightingAsync( "[|<@|] [|@$$>|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestOnRightOfCloseBrace() { await TestBraceHighlightingAsync( "[|<@|] [|@>$$|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotAfterBrace() { await TestBraceHighlightingAsync( "<@ @> $$"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotOnBrace2() { await TestBraceHighlightingAsync( "$$ <@ @><@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestOnLeftOfStartBrace2() { await TestBraceHighlightingAsync( "$$[|<@|] [|@>|]<@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestInsideStartBrace2() { await TestBraceHighlightingAsync( "[|<$$@|] [|@>|]<@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotOnRightOfStartBrace2() { await TestBraceHighlightingAsync( "<@$$ @><@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotOnLeftOfCloseBrace2() { await TestBraceHighlightingAsync( "<@ $$@><@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestInsideCloseBrace3() { await TestBraceHighlightingAsync( "[|<@|] [|@$$>|]<@ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestOnRightOfCloseBrace2() { await TestBraceHighlightingAsync( "[|<@|] [|@>|]$$[|<@|] [|@>|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestInSecondBracePair() { await TestBraceHighlightingAsync( "<@ @>[|<$$@|] [|@>|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotAfterSecondBracePairStart() { await TestBraceHighlightingAsync( "<@ @><@$$ @>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotBeforeSecondBracePairEnd() { await TestBraceHighlightingAsync( "<@ @><@ $$@>"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestInSecondBracePairEnd() { await TestBraceHighlightingAsync( "<@ @>[|<@|] [|@$$>|]"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestAtSecondBracePairEnd() { await TestBraceHighlightingAsync( "<@ @>[|<@|] [|@>|]$$"); } - [WorkItem("https://github.com/dotnet/roslyn/issues/18050")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/18050")] public async Task TestNotAfterSecondBracePairEnd() { await TestBraceHighlightingAsync( diff --git a/src/EditorFeatures/TestUtilities/CompleteStatement/AbstractCompleteStatementTests.cs b/src/EditorFeatures/TestUtilities/CompleteStatement/AbstractCompleteStatementTests.cs index 99d8027935497..897f7a207e321 100644 --- a/src/EditorFeatures/TestUtilities/CompleteStatement/AbstractCompleteStatementTests.cs +++ b/src/EditorFeatures/TestUtilities/CompleteStatement/AbstractCompleteStatementTests.cs @@ -6,11 +6,13 @@ using System.Linq; using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; using Roslyn.Test.Utilities; +using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.UnitTests.CompleteStatement @@ -27,19 +29,38 @@ public abstract class AbstractCompleteStatementTests /// /// Verify that typing a semicolon at the location in /// marked with - /// - $$ for caret position - /// - or, [| and |] for selected span + /// - one or more $$ for caret positions to test + /// - or, [| and |] for testing a selected span /// does not perform any special "complete statement" operations, e.g. inserting missing /// delimiters or moving the caret prior to the semicolon character insertion. In other words, /// statement completion does not impact typing behavior for the case. /// protected void VerifyNoSpecialSemicolonHandling(string initialMarkup) { - var expected = initialMarkup.Contains("$$") - ? initialMarkup.Replace("$$", ";$$") - : initialMarkup.Replace("|]", ";$$|]"); + TestFileMarkupParser.GetPositionsAndSpans(initialMarkup, out var output, out var positions, out var spans); + Contract.ThrowIfTrue(positions.IsEmpty && spans.IsEmpty, "Expected at least one test position"); + Contract.ThrowIfTrue(!positions.IsEmpty && !spans.IsEmpty, "Cannot test positions and spans at the same time"); - VerifyTypingSemicolon(initialMarkup, expected); + foreach (var position in positions) + { + VerifyTypingSemicolon( + output.Insert(position, "$$"), + output.Insert(position, ";$$")); + } + + if (!spans.IsEmpty) + { + // Only allow unnamed spans for these tests + Contract.ThrowIfFalse(spans.Keys.ToArray() is [""]); + + foreach (var span in spans[""]) + { + // Insert the end text first so the second insertion position doesn't require an offset + VerifyTypingSemicolon( + output.Insert(span.End, "|]").Insert(span.Start, "[|"), + output.Insert(span.End, ";$$|]").Insert(span.Start, "[|")); + } + } } /// @@ -99,7 +120,7 @@ protected void Verify(string initialMarkup, string expectedMarkup, setOptions?.Invoke(workspace); execute(view, workspace); - MarkupTestFile.GetPosition(expectedMarkup, out var expectedCode, out int expectedPosition); + TestFileMarkupParser.GetPosition(expectedMarkup, out var expectedCode, out var expectedPosition); AssertEx.EqualOrDiff(expectedCode, view.TextSnapshot.GetText()); diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 9182640df9684..2c42f7a106105 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -241,7 +241,7 @@ private async Task VerifyAsync( string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, List matchingFilters, CompletionItemFlags? flags, CompletionOptions options, bool skipSpeculation = false) { - foreach (var sourceKind in sourceCodeKind.HasValue ? new[] { sourceCodeKind.Value } : new[] { SourceCodeKind.Regular, SourceCodeKind.Script }) + foreach (var sourceKind in sourceCodeKind.HasValue ? [sourceCodeKind.Value] : new[] { SourceCodeKind.Regular, SourceCodeKind.Script }) { using var workspaceFixture = GetOrCreateWorkspaceFixture(); diff --git a/src/EditorFeatures/TestUtilities/QuickInfo/ToolTipAssert.cs b/src/EditorFeatures/TestUtilities/QuickInfo/ToolTipAssert.cs index 330de55321e16..e49efc27989a8 100644 --- a/src/EditorFeatures/TestUtilities/QuickInfo/ToolTipAssert.cs +++ b/src/EditorFeatures/TestUtilities/QuickInfo/ToolTipAssert.cs @@ -137,7 +137,7 @@ private static void ContainerToString(object element, string indent, StringBuild if (i < elements.Length - 1) result.AppendLine(","); else - result.Append(")"); + result.Append(')'); } return; @@ -163,7 +163,7 @@ private static void ContainerToString(object element, string indent, StringBuild if (i < runs.Length - 1) result.AppendLine(","); else - result.Append(")"); + result.Append(')'); } return; @@ -193,7 +193,7 @@ private static void ContainerToString(object element, string indent, StringBuild result.Append($", {TextRunStyleToString(classifiedTextRun.Style)}"); } - result.Append(")"); + result.Append(')'); return; } diff --git a/src/EditorFeatures/Text/Extensions.SnapshotSourceText.cs b/src/EditorFeatures/Text/Extensions.SnapshotSourceText.cs index a71d45b188223..118b7fb91de94 100644 --- a/src/EditorFeatures/Text/Extensions.SnapshotSourceText.cs +++ b/src/EditorFeatures/Text/Extensions.SnapshotSourceText.cs @@ -301,7 +301,7 @@ public override IReadOnlyList GetChangeRanges(SourceText oldTex if (oldText != _baseText) { - return new[] { new TextChangeRange(new TextSpan(0, oldText.Length), this.Length) }; + return [new TextChangeRange(new TextSpan(0, oldText.Length), this.Length)]; } return GetChangeRanges(_baseSnapshot, _baseSnapshot.Length, this.TextImage); @@ -393,7 +393,7 @@ private static IReadOnlyList GetChangeRanges(ITextImage snapsho // Oops - more than one "textual" change between these snapshots, bail and try to find smallest changes span Logger.Log(FunctionId.Workspace_SourceText_GetChangeRanges, s_textLog, snapshot1.Version.VersionNumber, snapshot2.Version.VersionNumber); - return new[] { GetChangeRanges(oldSnapshot.Version, newSnapshot.Version, forward) }; + return [GetChangeRanges(oldSnapshot.Version, newSnapshot.Version, forward)]; } else { diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/CompileExpressionsTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/CompileExpressionsTests.cs index d37e0376ec3cb..df47eee9c8990 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/CompileExpressionsTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/CompileExpressionsTests.cs @@ -1028,8 +1028,7 @@ .maxstack 1 } [WorkItem("https://github.com/dotnet/roslyn/issues/66109")] - [WorkItem("https://github.com/dotnet/roslyn/issues/64098")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/64098")] public void FileLocalType_07() { var sourceA = """ @@ -1178,8 +1177,7 @@ .maxstack 1 }); } - [WorkItem("https://github.com/dotnet/roslyn/issues/66109")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/66109")] public void SequencePointsMultipleDocuments_01() { var sourceA = @@ -1356,8 +1354,7 @@ .locals init (int V_0) //z }); } - [WorkItem("https://github.com/dotnet/roslyn/issues/66109")] - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/66109")] public void SequencePointsMultipleDocuments_02() { var sourceA = """ diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs index 25922de0a50d2..d5281c3a50157 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/DynamicTests.cs @@ -1500,10 +1500,7 @@ private static void VerifyCustomTypeInfo(Guid customTypeInfoId, ReadOnlyCollecti { Assert.Equal(CustomTypeInfo.PayloadTypeId, customTypeInfoId); // Include leading count byte. - var builder = ArrayBuilder.GetInstance(); - builder.Add((byte)expectedBytes.Length); - builder.AddRange(expectedBytes); - expectedBytes = builder.ToArrayAndFree(); + expectedBytes = [(byte)expectedBytes.Length, .. expectedBytes]; Assert.Equal(expectedBytes, customTypeInfo); } } diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs index 15ff176129182..4265193e41e3c 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs @@ -7050,8 +7050,7 @@ .locals init (int V_0, //i }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_01() { var source = @@ -7112,8 +7111,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_02() { var source = @@ -7173,8 +7171,7 @@ .maxstack 1 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_03() { var source = @@ -7237,8 +7234,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_04() { var source = @@ -7299,8 +7295,7 @@ .maxstack 1 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_05() { var source = @@ -7358,8 +7353,7 @@ .locals init (C.<>c__DisplayClass0_0 V_0, //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_06() { var source = @@ -7417,8 +7411,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_07() { var source = @@ -7475,8 +7468,7 @@ .locals init (int V_0, //x }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_11() { var source = @@ -7530,8 +7522,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_12() { var source = @@ -7584,8 +7575,7 @@ .maxstack 1 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_13() { var source = @@ -7641,8 +7631,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0) //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_14() { var source = @@ -7697,8 +7686,7 @@ .maxstack 1 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_15() { var source = @@ -7755,8 +7743,7 @@ .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_16() { var source = @@ -7813,8 +7800,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0) //CS$<>8__locals0 }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_17() { var source = @@ -7871,8 +7857,7 @@ .locals init (int V_0, //x }"); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] [WorkItem(67188, "https://github.com/dotnet/roslyn/issues/67188")] public void CapturingAndShadowing_18() { diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalFunctionTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalFunctionTests.cs index d9185677cf578..604dede5084af 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalFunctionTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalFunctionTests.cs @@ -273,8 +273,7 @@ .locals init (int V_0) // Should not bind to unnamed display class parameters // (unnamed parameters are treated as named "value"). - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18426")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18426")] public void DisplayClassParameter_01() { var source = @@ -300,8 +299,7 @@ int G() }); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18426")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18426")] public void DisplayClassParameter_02() { var source = @@ -340,8 +338,7 @@ .locals init (int V_0) }); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18426")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18426")] public void DisplayClassParameter_03() { var source = diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs index c5358de1a7788..2e64dded07bb1 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/LocalsTests.cs @@ -1452,8 +1452,7 @@ .maxstack 2 }); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69117")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69117")] public void CapturedParameters() { var source = @" @@ -5229,8 +5228,7 @@ .locals init (T V_0) //t }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_01() { var source = @@ -5338,8 +5336,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_02() { var source = @@ -5426,8 +5423,7 @@ .maxstack 1 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_03() { var source = @@ -5529,8 +5525,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_04() { var source = @@ -5614,8 +5609,7 @@ .maxstack 1 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_05() { var source = @@ -5716,8 +5710,7 @@ .locals init (C.<>c__DisplayClass0_0 V_0, //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_06() { var source = @@ -5830,8 +5823,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_07() { var source = @@ -5918,8 +5910,7 @@ .locals init (int V_0, //x }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_11() { var source = @@ -6004,8 +5995,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0, //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_12() { var source = @@ -6084,8 +6074,7 @@ .maxstack 1 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_13() { var source = @@ -6165,8 +6154,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0) //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_14() { var source = @@ -6243,8 +6231,7 @@ .maxstack 1 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_15() { var source = @@ -6320,8 +6307,7 @@ .locals init (C.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_16() { var source = @@ -6407,8 +6393,7 @@ .locals init (C.<>c__DisplayClass0_1 V_0) //CS$<>8__locals0 }); } - [Fact] - [WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] + [Fact, WorkItem(67177, "https://github.com/dotnet/roslyn/issues/67177")] public void CapturingAndShadowing_17() { var source = diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/ReflectionUtilities.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/ReflectionUtilities.cs index 37b9599074121..c46088fa8a4c1 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/ReflectionUtilities.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/ReflectionUtilities.cs @@ -41,19 +41,21 @@ internal static AssemblyLoadContext LoadAssemblies(params Assembly[] assemblies) internal static Assembly[] GetMscorlib(params Assembly[] additionalAssemblies) { - var builder = ArrayBuilder.GetInstance(); - builder.Add(typeof(object).Assembly); // mscorlib.dll - builder.AddRange(additionalAssemblies); - return builder.ToArrayAndFree(); + return + [ + typeof(object).Assembly, // mscorlib.dll + .. additionalAssemblies, + ]; } internal static Assembly[] GetMscorlibAndSystemCore(params Assembly[] additionalAssemblies) { - var builder = ArrayBuilder.GetInstance(); - builder.Add(typeof(object).Assembly); // mscorlib.dll - builder.Add(typeof(Enumerable).Assembly); // System.Core.dll - builder.AddRange(additionalAssemblies); - return builder.ToArrayAndFree(); + return + [ + typeof(object).Assembly, // mscorlib.dll + typeof(Enumerable).Assembly, // System.Core.dll + .. additionalAssemblies, + ]; } internal sealed class AssemblyLoadContext : IDisposable diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs index f975b2faf9285..d7e5c3b99275d 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/ResultProviderTestBase.cs @@ -410,7 +410,7 @@ private static string ToString(DkmSuccessEvaluationResult result) builder.Append(", "); builder.Append(Quote(result.EditableValue)); } - builder.Append(")"); + builder.Append(')'); return pooledBuilder.ToStringAndFree(); } @@ -437,7 +437,7 @@ private static string ToString(DkmIntermediateEvaluationResult result) builder.Append(", "); builder.Append(FormatEnumValue(result.Flags)); } - builder.Append(")"); + builder.Append(')'); return pooledBuilder.ToStringAndFree(); } @@ -464,7 +464,7 @@ private static string ToString(DkmFailedEvaluationResult result) builder.Append(", "); builder.Append(FormatEnumValue(result.Flags)); } - builder.Append(")"); + builder.Append(')'); return pooledBuilder.ToStringAndFree(); } diff --git a/src/Features/CSharp/Portable/CodeRefactorings/ConvertLocalFunctionToMethod/CSharpConvertLocalFunctionToMethodCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/ConvertLocalFunctionToMethod/CSharpConvertLocalFunctionToMethodCodeRefactoringProvider.cs index a912c591d86a7..e9d1997514994 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/ConvertLocalFunctionToMethod/CSharpConvertLocalFunctionToMethodCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/ConvertLocalFunctionToMethod/CSharpConvertLocalFunctionToMethodCodeRefactoringProvider.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.Collections.Generic; using System.Collections.Immutable; using System.Composition; @@ -23,307 +21,301 @@ using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.ConvertLocalFunctionToMethod +namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.ConvertLocalFunctionToMethod; + +[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.ConvertLocalFunctionToMethod), Shared] +[method: ImportingConstructor] +[method: SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] +internal sealed class CSharpConvertLocalFunctionToMethodCodeRefactoringProvider() : CodeRefactoringProvider { - [ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.ConvertLocalFunctionToMethod), Shared] - internal sealed class CSharpConvertLocalFunctionToMethodCodeRefactoringProvider : CodeRefactoringProvider + private static readonly SyntaxAnnotation s_delegateToReplaceAnnotation = new(); + + public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { - private static readonly SyntaxAnnotation s_delegateToReplaceAnnotation = new(); + var (document, textSpan, cancellationToken) = context; + if (document.Project.Solution.WorkspaceKind == WorkspaceKind.MiscellaneousFiles) + return; + + var localFunction = await context.TryGetRelevantNodeAsync().ConfigureAwait(false); + if (localFunction == null) + return; + + if (localFunction.Parent is not BlockSyntax parentBlock) + return; + + var container = localFunction.GetAncestor(); + + // If the local function is defined in a block within the top-level statements context, then we can't provide the refactoring because + // there is no class we can put the generated method in. + if (container == null || container is GlobalStatementSyntax or FieldDeclarationSyntax or EventFieldDeclarationSyntax) + return; + + var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var containerSymbol = semanticModel.GetDeclaredSymbol(container); + if (containerSymbol is null) + return; + + context.RegisterRefactoring( + CodeAction.Create( + CSharpFeaturesResources.Convert_to_method, + c => UpdateDocumentAsync(document, parentBlock, localFunction, container, context.Options, c), + nameof(CSharpFeaturesResources.Convert_to_method)), + localFunction.Span); + } - [ImportingConstructor] - [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] - public CSharpConvertLocalFunctionToMethodCodeRefactoringProvider() - { - } + private static async Task UpdateDocumentAsync( + Document document, + BlockSyntax parentBlock, + LocalFunctionStatementSyntax localFunction, + MemberDeclarationSyntax container, + CodeGenerationOptionsProvider fallbackOptions, + CancellationToken cancellationToken) + { + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var declaredSymbol = semanticModel.GetRequiredDeclaredSymbol(localFunction, cancellationToken); + + Contract.ThrowIfTrue(localFunction.Body is null && localFunction.ExpressionBody is null); + + var dataFlow = semanticModel.AnalyzeDataFlow( + localFunction.Body ?? (SyntaxNode)localFunction.ExpressionBody!.Expression); - public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) + // Exclude local function parameters in case they were captured inside the function body + var captures = dataFlow.CapturedInside.Except(dataFlow.VariablesDeclared).Except(declaredSymbol.Parameters).ToList(); + + // First, create a parameter per each capture so that we can pass them as arguments to the final method + // Filter out `this` because it doesn't need a parameter, we will just make a non-static method for that + // We also make a `ref` parameter here for each capture that is being written into inside the function + var capturesAsParameters = captures + .Where(capture => !capture.IsThisParameter()) + .Select(capture => CodeGenerationSymbolFactory.CreateParameterSymbol( + attributes: default, + refKind: dataFlow.WrittenInside.Contains(capture) ? RefKind.Ref : RefKind.None, + isParams: false, + type: capture.GetSymbolType() ?? semanticModel.Compilation.ObjectType, + name: capture.Name)).ToList(); + + // Find all enclosing type parameters e.g. from outer local functions and the containing member + // We exclude the containing type itself which has type parameters accessible to all members + var typeParameters = new List(); + AddCapturedTypeParameters(declaredSymbol, typeParameters); + + // We're going to remove unreferenced type parameters but we explicitly preserve + // captures' types, just in case that they were not spelt out in the function body + var captureTypes = captures.SelectMany(capture => capture.GetSymbolType().GetReferencedTypeParameters()); + RemoveUnusedTypeParameters(localFunction, semanticModel, typeParameters, reservedTypeParameters: captureTypes); + + var containerSymbol = semanticModel.GetRequiredDeclaredSymbol(container, cancellationToken); + var isStatic = containerSymbol.IsStatic || captures.All(capture => !capture.IsThisParameter()); + + // GetSymbolModifiers actually checks if the local function needs to be unsafe, not whether + // it is declared as such, so this check we don't need to worry about whether the containing method + // is unsafe, this will just work regardless. + var needsUnsafe = declaredSymbol.GetSymbolModifiers().IsUnsafe; + + var methodName = GenerateUniqueMethodName(declaredSymbol); + var parameters = declaredSymbol.Parameters; + var methodSymbol = CodeGenerationSymbolFactory.CreateMethodSymbol( + containingType: declaredSymbol.ContainingType, + attributes: default, + accessibility: Accessibility.Private, + modifiers: new DeclarationModifiers(isStatic, isAsync: declaredSymbol.IsAsync, isUnsafe: needsUnsafe), + returnType: declaredSymbol.ReturnType, + refKind: declaredSymbol.RefKind, + explicitInterfaceImplementations: default, + name: methodName, + typeParameters: [.. typeParameters], + parameters: parameters.AddRange(capturesAsParameters)); + + var info = (CSharpCodeGenerationContextInfo)await document.GetCodeGenerationInfoAsync(CodeGenerationContext.Default, fallbackOptions, cancellationToken).ConfigureAwait(false); + var method = MethodGenerator.GenerateMethodDeclaration(methodSymbol, CodeGenerationDestination.Unspecified, info, cancellationToken); + + if (localFunction.AttributeLists.Count > 0) + method = method.WithoutLeadingTrivia().WithAttributeLists(localFunction.AttributeLists).WithLeadingTrivia(method.GetLeadingTrivia()); + + var generator = CSharpSyntaxGenerator.Instance; + var editor = new SyntaxEditor(root, generator); + + var needsRename = methodName != declaredSymbol.Name; + var identifierToken = needsRename ? methodName.ToIdentifierToken() : default; + var supportsNonTrailing = SupportsNonTrailingNamedArguments(root.SyntaxTree.Options); + var hasAdditionalArguments = !capturesAsParameters.IsEmpty(); + var additionalTypeParameters = typeParameters.Except(declaredSymbol.TypeParameters).ToList(); + var hasAdditionalTypeArguments = !additionalTypeParameters.IsEmpty(); + var additionalTypeArguments = hasAdditionalTypeArguments + ? additionalTypeParameters.Select(p => (TypeSyntax)p.Name.ToIdentifierName()).ToArray() + : null; + + var anyDelegatesToReplace = false; + // Update callers' name, arguments and type arguments + foreach (var node in parentBlock.DescendantNodes()) { - var (document, textSpan, cancellationToken) = context; - if (document.Project.Solution.WorkspaceKind == WorkspaceKind.MiscellaneousFiles) + // A local function reference can only be an identifier or a generic name. + switch (node.Kind()) { - return; + case SyntaxKind.IdentifierName: + case SyntaxKind.GenericName: + break; + default: + continue; } - var localFunction = await context.TryGetRelevantNodeAsync().ConfigureAwait(false); - if (localFunction == null) + // Using symbol to get type arguments, since it could be inferred and not present in the source + var symbol = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol as IMethodSymbol; + if (!Equals(symbol?.OriginalDefinition, declaredSymbol)) { - return; + continue; } - if (localFunction.Parent is not BlockSyntax parentBlock) + var currentNode = node; + + if (needsRename) { - return; + currentNode = ((SimpleNameSyntax)currentNode).WithIdentifier(identifierToken); } - var container = localFunction.GetAncestor(); - // If the local function is defined in a block within the top-level statements context, then we can't provide the refactoring because - // there is no class we can put the generated method in. - if (container == null || container.IsKind(SyntaxKind.GlobalStatement)) + if (hasAdditionalTypeArguments) { - return; + var existingTypeArguments = symbol.TypeArguments.Select(s => s.GenerateTypeSyntax()); + // Prepend additional type arguments to preserve lexical order in which they are defined + Contract.ThrowIfNull(additionalTypeArguments); + var typeArguments = additionalTypeArguments.Concat(existingTypeArguments); + currentNode = generator.WithTypeArguments(currentNode, typeArguments); + currentNode = currentNode.WithAdditionalAnnotations(Simplifier.Annotation); } - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - - context.RegisterRefactoring( - CodeAction.Create( - CSharpFeaturesResources.Convert_to_method, - c => UpdateDocumentAsync(root, document, parentBlock, localFunction, container, context.Options, c), - nameof(CSharpFeaturesResources.Convert_to_method)), - localFunction.Span); - } - - private static async Task UpdateDocumentAsync( - SyntaxNode root, - Document document, - BlockSyntax parentBlock, - LocalFunctionStatementSyntax localFunction, - MemberDeclarationSyntax container, - CodeGenerationOptionsProvider fallbackOptions, - CancellationToken cancellationToken) - { - var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var declaredSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(localFunction, cancellationToken); - - var dataFlow = semanticModel.AnalyzeDataFlow( - localFunction.Body ?? (SyntaxNode)localFunction.ExpressionBody.Expression); - - // Exclude local function parameters in case they were captured inside the function body - var captures = dataFlow.CapturedInside.Except(dataFlow.VariablesDeclared).Except(declaredSymbol.Parameters).ToList(); - - // First, create a parameter per each capture so that we can pass them as arguments to the final method - // Filter out `this` because it doesn't need a parameter, we will just make a non-static method for that - // We also make a `ref` parameter here for each capture that is being written into inside the function - var capturesAsParameters = captures - .Where(capture => !capture.IsThisParameter()) - .Select(capture => CodeGenerationSymbolFactory.CreateParameterSymbol( - attributes: default, - refKind: dataFlow.WrittenInside.Contains(capture) ? RefKind.Ref : RefKind.None, - isParams: false, - type: capture.GetSymbolType(), - name: capture.Name)).ToList(); - - // Find all enclosing type parameters e.g. from outer local functions and the containing member - // We exclude the containing type itself which has type parameters accessible to all members - var typeParameters = new List(); - AddCapturedTypeParameters(declaredSymbol, typeParameters); - - // We're going to remove unreferenced type parameters but we explicitly preserve - // captures' types, just in case that they were not spelt out in the function body - var captureTypes = captures.SelectMany(capture => capture.GetSymbolType().GetReferencedTypeParameters()); - RemoveUnusedTypeParameters(localFunction, semanticModel, typeParameters, reservedTypeParameters: captureTypes); - - var containerSymbol = semanticModel.GetDeclaredSymbol(container, cancellationToken); - var isStatic = containerSymbol.IsStatic || captures.All(capture => !capture.IsThisParameter()); - - // GetSymbolModifiers actually checks if the local function needs to be unsafe, not whether - // it is declared as such, so this check we don't need to worry about whether the containing method - // is unsafe, this will just work regardless. - var needsUnsafe = declaredSymbol.GetSymbolModifiers().IsUnsafe; - - var methodName = GenerateUniqueMethodName(declaredSymbol); - var parameters = declaredSymbol.Parameters; - var methodSymbol = CodeGenerationSymbolFactory.CreateMethodSymbol( - containingType: declaredSymbol.ContainingType, - attributes: default, - accessibility: Accessibility.Private, - modifiers: new DeclarationModifiers(isStatic, isAsync: declaredSymbol.IsAsync, isUnsafe: needsUnsafe), - returnType: declaredSymbol.ReturnType, - refKind: declaredSymbol.RefKind, - explicitInterfaceImplementations: default, - name: methodName, - typeParameters: typeParameters.ToImmutableArray(), - parameters: parameters.AddRange(capturesAsParameters)); - - var info = (CSharpCodeGenerationContextInfo)await document.GetCodeGenerationInfoAsync(CodeGenerationContext.Default, fallbackOptions, cancellationToken).ConfigureAwait(false); - var method = MethodGenerator.GenerateMethodDeclaration(methodSymbol, CodeGenerationDestination.Unspecified, info, cancellationToken); - - if (localFunction.AttributeLists.Count > 0) - method = method.WithoutLeadingTrivia().WithAttributeLists(localFunction.AttributeLists).WithLeadingTrivia(method.GetLeadingTrivia()); - - var generator = CSharpSyntaxGenerator.Instance; - var editor = new SyntaxEditor(root, generator); - - var needsRename = methodName != declaredSymbol.Name; - var identifierToken = needsRename ? methodName.ToIdentifierToken() : default; - var supportsNonTrailing = SupportsNonTrailingNamedArguments(root.SyntaxTree.Options); - var hasAdditionalArguments = !capturesAsParameters.IsEmpty(); - var additionalTypeParameters = typeParameters.Except(declaredSymbol.TypeParameters).ToList(); - var hasAdditionalTypeArguments = !additionalTypeParameters.IsEmpty(); - var additionalTypeArguments = hasAdditionalTypeArguments - ? additionalTypeParameters.Select(p => (TypeSyntax)p.Name.ToIdentifierName()).ToArray() - : null; - - var anyDelegatesToReplace = false; - // Update callers' name, arguments and type arguments - foreach (var node in parentBlock.DescendantNodes()) + if (node.Parent is InvocationExpressionSyntax invocation) { - // A local function reference can only be an identifier or a generic name. - switch (node.Kind()) + if (hasAdditionalArguments) { - case SyntaxKind.IdentifierName: - case SyntaxKind.GenericName: - break; - default: - continue; - } + var shouldUseNamedArguments = + !supportsNonTrailing && invocation.ArgumentList.Arguments.Any(arg => arg.NameColon != null); - // Using symbol to get type arguments, since it could be inferred and not present in the source - var symbol = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol as IMethodSymbol; - if (!Equals(symbol?.OriginalDefinition, declaredSymbol)) - { - continue; - } + var additionalArguments = capturesAsParameters.Select(p => + (ArgumentSyntax)GenerateArgument(p, p.Name, shouldUseNamedArguments)).ToArray(); - var currentNode = node; - - if (needsRename) - { - currentNode = ((SimpleNameSyntax)currentNode).WithIdentifier(identifierToken); + editor.ReplaceNode(invocation.ArgumentList, + invocation.ArgumentList.AddArguments(additionalArguments)); } + } + else if (hasAdditionalArguments || hasAdditionalTypeArguments) + { + // Convert local function delegates to lambda if the signature no longer matches + currentNode = currentNode.WithAdditionalAnnotations(s_delegateToReplaceAnnotation); + anyDelegatesToReplace = true; + } - if (hasAdditionalTypeArguments) - { - var existingTypeArguments = symbol.TypeArguments.Select(s => s.GenerateTypeSyntax()); - // Prepend additional type arguments to preserve lexical order in which they are defined - var typeArguments = additionalTypeArguments.Concat(existingTypeArguments); - currentNode = generator.WithTypeArguments(currentNode, typeArguments); - currentNode = currentNode.WithAdditionalAnnotations(Simplifier.Annotation); - } - - if (node.Parent is InvocationExpressionSyntax invocation) - { - if (hasAdditionalArguments) - { - var shouldUseNamedArguments = - !supportsNonTrailing && invocation.ArgumentList.Arguments.Any(arg => arg.NameColon != null); - - var additionalArguments = capturesAsParameters.Select(p => - (ArgumentSyntax)GenerateArgument(p, p.Name, shouldUseNamedArguments)).ToArray(); - - editor.ReplaceNode(invocation.ArgumentList, - invocation.ArgumentList.AddArguments(additionalArguments)); - } - } - else if (hasAdditionalArguments || hasAdditionalTypeArguments) - { - // Convert local function delegates to lambda if the signature no longer matches - currentNode = currentNode.WithAdditionalAnnotations(s_delegateToReplaceAnnotation); - anyDelegatesToReplace = true; - } + editor.ReplaceNode(node, currentNode); + } - editor.ReplaceNode(node, currentNode); - } + editor.TrackNode(localFunction); + editor.TrackNode(container); - editor.TrackNode(localFunction); - editor.TrackNode(container); + root = editor.GetChangedRoot(); - root = editor.GetChangedRoot(); + localFunction = root.GetCurrentNode(localFunction) ?? throw ExceptionUtilities.Unreachable(); + container = root.GetCurrentNode(container) ?? throw ExceptionUtilities.Unreachable(); - localFunction = root.GetCurrentNode(localFunction); - container = root.GetCurrentNode(container); + method = WithBodyFrom(method, localFunction); - method = WithBodyFrom(method, localFunction); + editor = new SyntaxEditor(root, generator); + editor.InsertAfter(container, method); + editor.RemoveNode(localFunction, SyntaxRemoveOptions.KeepNoTrivia); + if (anyDelegatesToReplace) + { + document = document.WithSyntaxRoot(editor.GetChangedRoot()); + semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); editor = new SyntaxEditor(root, generator); - editor.InsertAfter(container, method); - editor.RemoveNode(localFunction, SyntaxRemoveOptions.KeepNoTrivia); - if (anyDelegatesToReplace) + foreach (var node in root.GetAnnotatedNodes(s_delegateToReplaceAnnotation)) { - document = document.WithSyntaxRoot(editor.GetChangedRoot()); - semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - editor = new SyntaxEditor(root, generator); + var reservedNames = GetReservedNames(node, semanticModel, cancellationToken); + var parameterNames = GenerateUniqueParameterNames(parameters, reservedNames); + var lambdaParameters = parameters.Zip(parameterNames, (p, name) => GenerateParameter(p, name)); + var lambdaArguments = parameters.Zip(parameterNames, (p, name) => GenerateArgument(p, name)); + var additionalArguments = capturesAsParameters.Select(p => GenerateArgument(p, p.Name)); + var newNode = generator.ValueReturningLambdaExpression(lambdaParameters, + generator.InvocationExpression(node, lambdaArguments.Concat(additionalArguments))); - foreach (var node in root.GetAnnotatedNodes(s_delegateToReplaceAnnotation)) + newNode = newNode.WithAdditionalAnnotations(Simplifier.Annotation); + + if (node.IsParentKind(SyntaxKind.CastExpression)) { - var reservedNames = GetReservedNames(node, semanticModel, cancellationToken); - var parameterNames = GenerateUniqueParameterNames(parameters, reservedNames); - var lambdaParameters = parameters.Zip(parameterNames, (p, name) => GenerateParameter(p, name)); - var lambdaArguments = parameters.Zip(parameterNames, (p, name) => GenerateArgument(p, name)); - var additionalArguments = capturesAsParameters.Select(p => GenerateArgument(p, p.Name)); - var newNode = generator.ValueReturningLambdaExpression(lambdaParameters, - generator.InvocationExpression(node, lambdaArguments.Concat(additionalArguments))); - - newNode = newNode.WithAdditionalAnnotations(Simplifier.Annotation); - - if (node.IsParentKind(SyntaxKind.CastExpression)) - { - newNode = ((ExpressionSyntax)newNode).Parenthesize(); - } - - editor.ReplaceNode(node, newNode); + newNode = ((ExpressionSyntax)newNode).Parenthesize(); } - } - return document.WithSyntaxRoot(editor.GetChangedRoot()); + editor.ReplaceNode(node, newNode); + } } - private static bool SupportsNonTrailingNamedArguments(ParseOptions options) - => options.LanguageVersion() >= LanguageVersion.CSharp7_2; + return document.WithSyntaxRoot(editor.GetChangedRoot()); + } - private static SyntaxNode GenerateArgument(IParameterSymbol p, string name, bool shouldUseNamedArguments = false) - => CSharpSyntaxGenerator.Instance.Argument(shouldUseNamedArguments ? name : null, p.RefKind, name.ToIdentifierName()); + private static bool SupportsNonTrailingNamedArguments(ParseOptions options) + => options.LanguageVersion() >= LanguageVersion.CSharp7_2; - private static List GenerateUniqueParameterNames(ImmutableArray parameters, List reservedNames) - => parameters.Select(p => NameGenerator.EnsureUniqueness(p.Name, reservedNames)).ToList(); + private static SyntaxNode GenerateArgument(IParameterSymbol p, string name, bool shouldUseNamedArguments = false) + => CSharpSyntaxGenerator.Instance.Argument(shouldUseNamedArguments ? name : null, p.RefKind, name.ToIdentifierName()); - private static List GetReservedNames(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) - => semanticModel.GetAllDeclaredSymbols(node.GetAncestor(), cancellationToken).Select(s => s.Name).ToList(); + private static List GenerateUniqueParameterNames(ImmutableArray parameters, List reservedNames) + => parameters.Select(p => NameGenerator.EnsureUniqueness(p.Name, reservedNames)).ToList(); - private static ParameterSyntax GenerateParameter(IParameterSymbol p, string name) - { - return SyntaxFactory.Parameter(name.ToIdentifierToken()) - .WithModifiers(CSharpSyntaxGeneratorInternal.GetParameterModifiers(p.RefKind)) - .WithType(p.Type.GenerateTypeSyntax()); - } + private static List GetReservedNames(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) + => semanticModel.GetAllDeclaredSymbols(node.GetAncestor(), cancellationToken).Select(s => s.Name).ToList(); - private static MethodDeclarationSyntax WithBodyFrom( - MethodDeclarationSyntax method, LocalFunctionStatementSyntax localFunction) - { - return method - .WithExpressionBody(localFunction.ExpressionBody) - .WithSemicolonToken(localFunction.SemicolonToken) - .WithBody(localFunction.Body); - } + private static ParameterSyntax GenerateParameter(IParameterSymbol p, string name) + { + return SyntaxFactory.Parameter(name.ToIdentifierToken()) + .WithModifiers(CSharpSyntaxGeneratorInternal.GetParameterModifiers(p.RefKind)) + .WithType(p.Type.GenerateTypeSyntax()); + } - private static void AddCapturedTypeParameters(ISymbol symbol, List typeParameters) - { - var containingSymbol = symbol.ContainingSymbol; - if (containingSymbol != null && - containingSymbol.Kind != SymbolKind.NamedType) - { - AddCapturedTypeParameters(containingSymbol, typeParameters); - } + private static MethodDeclarationSyntax WithBodyFrom( + MethodDeclarationSyntax method, LocalFunctionStatementSyntax localFunction) + { + return method + .WithExpressionBody(localFunction.ExpressionBody) + .WithSemicolonToken(localFunction.SemicolonToken) + .WithBody(localFunction.Body); + } - typeParameters.AddRange(symbol.GetTypeParameters()); + private static void AddCapturedTypeParameters(ISymbol symbol, List typeParameters) + { + var containingSymbol = symbol.ContainingSymbol; + if (containingSymbol != null && + containingSymbol.Kind != SymbolKind.NamedType) + { + AddCapturedTypeParameters(containingSymbol, typeParameters); } - private static void RemoveUnusedTypeParameters( - SyntaxNode localFunction, - SemanticModel semanticModel, - List typeParameters, - IEnumerable reservedTypeParameters) + typeParameters.AddRange(symbol.GetTypeParameters()); + } + + private static void RemoveUnusedTypeParameters( + SyntaxNode localFunction, + SemanticModel semanticModel, + List typeParameters, + IEnumerable reservedTypeParameters) + { + var unusedTypeParameters = typeParameters.ToList(); + foreach (var id in localFunction.DescendantNodes().OfType()) { - var unusedTypeParameters = typeParameters.ToList(); - foreach (var id in localFunction.DescendantNodes().OfType()) + var symbol = semanticModel.GetSymbolInfo(id).Symbol; + if (symbol != null && symbol.OriginalDefinition is ITypeParameterSymbol typeParameter) { - var symbol = semanticModel.GetSymbolInfo(id).Symbol; - if (symbol != null && symbol.OriginalDefinition is ITypeParameterSymbol typeParameter) - { - unusedTypeParameters.Remove(typeParameter); - } + unusedTypeParameters.Remove(typeParameter); } - - typeParameters.RemoveRange(unusedTypeParameters.Except(reservedTypeParameters)); } - private static string GenerateUniqueMethodName(ISymbol declaredSymbol) - { - return NameGenerator.EnsureUniqueness( - baseName: declaredSymbol.Name, - reservedNames: declaredSymbol.ContainingType.GetMembers().Select(m => m.Name)); - } + typeParameters.RemoveRange(unusedTypeParameters.Except(reservedTypeParameters)); + } + + private static string GenerateUniqueMethodName(ISymbol declaredSymbol) + { + return NameGenerator.EnsureUniqueness( + baseName: declaredSymbol.Name, + reservedNames: declaredSymbol.ContainingType.GetMembers().Select(m => m.Name)); } } diff --git a/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs index 56a97228be4b6..c88d4906f38f3 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs @@ -161,7 +161,7 @@ private static async Task DisableNullableReferenceTypesInExistingDoc var existingTriviaList = firstToken.LeadingTrivia; var insertionIndex = GetInsertionPoint(existingTriviaList); - return root.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(existingTriviaList.InsertRange(insertionIndex, new[] { nullableDisableTrivia, newLine, newLine }))); + return root.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(existingTriviaList.InsertRange(insertionIndex, [nullableDisableTrivia, newLine, newLine]))); } else if (leadingDirective.SettingToken.IsKind(SyntaxKind.RestoreKeyword) && leadingDirective.TargetToken.IsKind(SyntaxKind.None)) { diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs index 0b65352b9266c..36a30a0d69460 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/OperatorsAndIndexer/UnnamedSymbolCompletionProvider_Operators.cs @@ -104,12 +104,6 @@ private void AddOperatorGroup(CompletionContext context, string opName, IEnumera return; var displayText = GetOperatorText(opName); - - using var _ = ArrayBuilder>.GetInstance(OperatorProperties.Length + 1, out var builder); - - builder.AddRange(OperatorProperties); - builder.Add(new KeyValuePair(OperatorName, opName)); - context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, displayTextSuffix: null, @@ -119,7 +113,7 @@ private void AddOperatorGroup(CompletionContext context, string opName, IEnumera symbols: operators.ToImmutableArray(), rules: s_operatorRules, contextPosition: context.Position, - properties: builder.ToImmutable(), + properties: [.. OperatorProperties, new KeyValuePair(OperatorName, opName)], isComplexTextEdit: true)); } diff --git a/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs b/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs index 2fb02c1959d35..e1d426c44362d 100644 --- a/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs +++ b/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs @@ -594,7 +594,7 @@ static StatementSyntax internalNodeMethod(ExpressionSyntax expression) var localFunctionInvocation = SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(localFunctionToken)).WithAdditionalAnnotations(Simplifier.Annotation); var newParentExpressionStatement = parentStatement.ReplaceNode(_source.WalkUpParentheses(), localFunctionInvocation.WithAdditionalAnnotations(Simplifier.Annotation)); - documentUpdateInfo = new DocumentUpdateInfo(parentStatement, new[] { localFunctionDeclaration, newParentExpressionStatement }); + documentUpdateInfo = new DocumentUpdateInfo(parentStatement, [localFunctionDeclaration, newParentExpressionStatement]); return true; } diff --git a/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/CSharpConvertForEachToLinqQueryProvider.cs b/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/CSharpConvertForEachToLinqQueryProvider.cs index efaa4b249f954..55e510411b94b 100644 --- a/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/CSharpConvertForEachToLinqQueryProvider.cs +++ b/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/CSharpConvertForEachToLinqQueryProvider.cs @@ -120,7 +120,7 @@ protected override ForEachInfo CreateFo } else { - statementsCannotBeConverted = new[] { current }; + statementsCannotBeConverted = [current]; break; } @@ -134,7 +134,7 @@ protected override ForEachInfo CreateFo else { // As above, if there is an empty initializer, stop processing. - statementsCannotBeConverted = new[] { current }; + statementsCannotBeConverted = [current]; } break; @@ -151,7 +151,7 @@ protected override ForEachInfo CreateFo default: // If no specific case found, stop processing. - statementsCannotBeConverted = new[] { current }; + statementsCannotBeConverted = [current]; break; } } diff --git a/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/YieldReturnConverter.cs b/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/YieldReturnConverter.cs index 229531db58d3d..50c3c75bc0a49 100644 --- a/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/YieldReturnConverter.cs +++ b/src/Features/CSharp/Portable/ConvertLinq/ConvertForEachToLinqQuery/YieldReturnConverter.cs @@ -24,7 +24,7 @@ public override void Convert(SyntaxEditor editor, bool convertToQuery, Cancellat { var queryOrLinqInvocationExpression = CreateQueryExpressionOrLinqInvocation( selectExpression: _yieldReturnStatement.Expression, - leadingTokensForSelect: new[] { _yieldReturnStatement.YieldKeyword, _yieldReturnStatement.ReturnOrBreakKeyword }, + leadingTokensForSelect: [_yieldReturnStatement.YieldKeyword, _yieldReturnStatement.ReturnOrBreakKeyword], trailingTokensForSelect: _yieldBreakStatement != null ? [_yieldReturnStatement.SemicolonToken, _yieldBreakStatement.YieldKeyword, diff --git a/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs index e2c8394b2a664..3e001256b88f8 100644 --- a/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs @@ -25,12 +25,12 @@ namespace Microsoft.CodeAnalysis.CSharp.ConvertToRawString; internal partial class ConvertStringToRawStringCodeRefactoringProvider : SyntaxEditorBasedCodeRefactoringProvider { private static readonly BidirectionalMap s_kindToEquivalenceKeyMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create(ConvertToRawKind.SingleLine, nameof(ConvertToRawKind.SingleLine)), KeyValuePairUtil.Create(ConvertToRawKind.MultiLineIndented, nameof(ConvertToRawKind.MultiLineIndented)), KeyValuePairUtil.Create(ConvertToRawKind.MultiLineWithoutLeadingWhitespace, nameof(ConvertToRawKind.MultiLineWithoutLeadingWhitespace)), - }); + ]); private static readonly ImmutableArray s_convertStringProviders = [ConvertRegularStringToRawStringProvider.Instance, ConvertInterpolatedStringToRawStringProvider.Instance]; diff --git a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs index 59c46e3f2b092..ed17282030724 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs @@ -2904,7 +2904,7 @@ private void ReportRudeEditsForSwitchWhenClauses(ArrayBuilder RemoveRedundantBlock(BlockSyntax var lastTokenWithAsset = block.CloseBraceToken.CopyAnnotationsTo(lastToken).WithAppendedTrailingTrivia(block.CloseBraceToken.GetAllTrivia()); // create new block with new tokens - block = block.ReplaceTokens(new[] { firstToken, lastToken }, (o, c) => (o == firstToken) ? firstTokenWithAsset : lastTokenWithAsset); + block = block.ReplaceTokens([firstToken, lastToken], (o, c) => (o == firstToken) ? firstTokenWithAsset : lastTokenWithAsset); // return only statements without the wrapping block return ImmutableArray.CreateRange(block.Statements); @@ -292,13 +292,12 @@ public static ImmutableArray RemoveDeclarationAssignmentPattern } var variable = declaration.Declaration.Variables[0].WithInitializer(SyntaxFactory.EqualsValueClause(assignmentExpression.Right)); - using var _ = ArrayBuilder.GetInstance(out var result); - - result.Add(declaration.WithDeclaration( - declaration.Declaration.WithVariables([variable]))); - result.AddRange(statements.Skip(2)); - - return result.ToImmutable(); + return + [ + declaration.WithDeclaration( + declaration.Declaration.WithVariables([variable])), + .. statements.Skip(2), + ]; } } } diff --git a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs index b949b989cd9e7..d1092a9fe65b7 100644 --- a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs +++ b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs @@ -780,7 +780,7 @@ internal override async Task TryAddUsingsOrImportToDocumentAsync( } var addImportOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); - var addedCompilationRoot = compilationRoot.AddUsingDirectives(new[] { usingDirective }, addImportOptions.PlaceSystemNamespaceFirst, Formatter.Annotation); + var addedCompilationRoot = compilationRoot.AddUsingDirectives([usingDirective], addImportOptions.PlaceSystemNamespaceFirst, Formatter.Annotation); updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, addedCompilationRoot, PreservationMode.PreserveIdentity); } diff --git a/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs b/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs index e03bea2c23e38..a7e61ea5a3bd6 100644 --- a/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs +++ b/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs @@ -426,17 +426,17 @@ private static SyntaxList InsertWithinTriviaOfNext( if (precedingEndOfLine == default) { return oldStatements.ReplaceRange( - nextStatement, new[] { newStatement, nextStatement }); + nextStatement, [newStatement, nextStatement]); } var endOfLineIndex = nextStatementLeading.IndexOf(precedingEndOfLine) + 1; return oldStatements.ReplaceRange( - nextStatement, new[] - { + nextStatement, + [ newStatement.WithLeadingTrivia(nextStatementLeading.Take(endOfLineIndex)), nextStatement.WithLeadingTrivia(nextStatementLeading.Skip(endOfLineIndex)), - }); + ]); } private static bool IsBlockLike(SyntaxNode node) => node is BlockSyntax or SwitchSectionSyntax; diff --git a/src/Features/CSharp/Portable/Structure/CSharpBlockStructureProvider.cs b/src/Features/CSharp/Portable/Structure/CSharpBlockStructureProvider.cs index d165f7b50e8b2..a680f96a5562f 100644 --- a/src/Features/CSharp/Portable/Structure/CSharpBlockStructureProvider.cs +++ b/src/Features/CSharp/Portable/Structure/CSharpBlockStructureProvider.cs @@ -51,6 +51,7 @@ private static ImmutableDictionary(); builder.Add(); builder.Add(); + builder.Add(); return builder.ToImmutable(); } diff --git a/src/Features/CSharp/Portable/Structure/Providers/CollectionExpressionStructureProvider.cs b/src/Features/CSharp/Portable/Structure/Providers/CollectionExpressionStructureProvider.cs new file mode 100644 index 0000000000000..34c438e9456aa --- /dev/null +++ b/src/Features/CSharp/Portable/Structure/Providers/CollectionExpressionStructureProvider.cs @@ -0,0 +1,72 @@ +// 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. + +using System.Collections.Generic; +using System.Threading; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Shared.Collections; +using Microsoft.CodeAnalysis.Structure; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.CSharp.Structure +{ + internal class CollectionExpressionStructureProvider : AbstractSyntaxNodeStructureProvider + { + protected override void CollectBlockSpans( + SyntaxToken previousToken, + CollectionExpressionSyntax node, + ref TemporaryArray spans, + BlockStructureOptions options, + CancellationToken cancellationToken) + { + if (node.Parent?.Parent is CollectionExpressionSyntax) + { + // We have something like: + // + // List> v = + // [ + // ... + // [ + // ... + // ], + // ... + // ]; + // + // In this case, we want to collapse the "[ ... ]," (including the comma). + + var nextToken = node.CloseBracketToken.GetNextToken(); + var end = nextToken.Kind() == SyntaxKind.CommaToken + ? nextToken.Span.End + : node.Span.End; + + var textSpan = TextSpan.FromBounds(node.SpanStart, end); + + spans.Add(new BlockSpan( + isCollapsible: true, + textSpan: textSpan, + hintSpan: textSpan, + type: BlockTypes.Expression)); + } + else + { + // Parent is something like: + // + // List v = + // [ + // ... + // ]; + // + // The collapsed textspan should be from the = to the ] + + var textSpan = TextSpan.FromBounds(previousToken.Span.End, node.Span.End); + + spans.Add(new BlockSpan( + isCollapsible: true, + textSpan: textSpan, + hintSpan: textSpan, + type: BlockTypes.Expression)); + } + } + } +} diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf index 86523fa361b7b..b384254337b26 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + Nelze určit platný rozsah příkazů k extrakci. @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + Převést na běžný konstruktor diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf index 8a65c2da9af58..df11ba002a89c 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + Impossible de déterminer la plage valide des instructions à extraire @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + Convertir en constructeur classique @@ -439,12 +439,12 @@ top-level code - code de niveau supérieur + Code de premier niveau top-level statement - instruction de niveau supérieur + Instructions de premier niveau diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf index 6aeb5c3b9e1b4..f6fb99eafcb9a 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + 抽出するステートメントの有効な範囲を決定できません @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + 通常のコンストラクターに変換する @@ -439,12 +439,12 @@ top-level code - 最上位レベルのコード + 最上位のコード top-level statement - 最上位レベルのステートメント + 最上位のステートメント diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf index 81c692aebf064..44dc5a417afb6 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + Nie można określić prawidłowego zakresu instrukcji do wyodrębnienia @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + Konwertuj na zwykłego konstruktora diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf index 68026a3513f33..512e5e9dce53e 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + Não é possível determinar o intervalo válido de instruções a serem extraídas @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + Converter em um construtor regular diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf index 21865becfeff6..071406fd95f07 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + Ayıklanacak geçerli deyim aralığı belirlenemedi @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + Normal oluşturucuya dönüştür diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf index ddd7e0e1f910e..ea7a9416ce097 100644 --- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf +++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf @@ -129,7 +129,7 @@ Cannot determine valid range of statements to extract - Cannot determine valid range of statements to extract + 無法判斷要擷取的有效陳述式範圍 @@ -159,7 +159,7 @@ Convert to regular constructor - Convert to regular constructor + 轉換為一般建構函式 @@ -439,12 +439,12 @@ top-level code - 最上層程式碼 + 最上層代碼 top-level statement - 最上層語句 + 最上層陳述式 diff --git a/src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs b/src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs index bd0a1636646e1..92b77134c79a5 100644 --- a/src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs +++ b/src/Features/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests.cs @@ -1036,8 +1036,7 @@ public int Goo await TestInRegularAndScriptAsync(text, expected, options: UseUnderscorePrefixedFieldName); } - [Fact] - [WorkItem(28013, "https://github.com/dotnet/roslyn/issues/26992")] + [Fact, WorkItem(28013, "https://github.com/dotnet/roslyn/issues/26992")] [WorkItem("https://github.com/dotnet/roslyn/issues/30208")] public async Task PropertyNameEqualsToClassNameExceptFirstCharCasingWhichCausesFieldNameCollisionByDefault() { diff --git a/src/Features/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs b/src/Features/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs index 447314640e961..a6e95f5bbfa59 100644 --- a/src/Features/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs +++ b/src/Features/CSharpTest/ConvertCast/ConvertDirectCastToTryCastTests.cs @@ -450,8 +450,7 @@ public static void Main() }.RunAsync(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/64466")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/64466")] public async Task ConvertFromExplicitToAs_NullableValueType() { const string InitialMarkup = """ diff --git a/src/Features/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs b/src/Features/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs index 06e49d97860d0..7a124319b2737 100644 --- a/src/Features/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs +++ b/src/Features/CSharpTest/ConvertCast/ConvertTryCastToDirectCastTests.cs @@ -265,8 +265,7 @@ public static void Main() }.RunAsync(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/64466")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/64466")] public async Task ConvertFromExplicitToAs_NullableValueType() { const string InitialMarkup = """ diff --git a/src/Features/CSharpTest/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs b/src/Features/CSharpTest/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs index 2aa4726973cad..fe4bf0850a660 100644 --- a/src/Features/CSharpTest/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs +++ b/src/Features/CSharpTest/ConvertLocalFunctionToMethod/ConvertLocalFunctionToMethodTests.cs @@ -1092,5 +1092,28 @@ private ref RefClass GetRef() } """); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72024")] + public async Task TestLocalFunctionInField() + { + await TestMissingInRegularAndScriptAsync( + """ + using System; + + class C + { + private Action a = () => + { + var s = default(S); + SetValue(3); + void [||]SetValue(int value) => s.Value = value; + } + } + struct S + { + public int Value; + } + """); + } } } diff --git a/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs b/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs index a1b34ef59e23f..f0fe4191e33dc 100644 --- a/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs +++ b/src/Features/CSharpTest/ConvertToRecord/ConvertToRecordCodeRefactoringTests.cs @@ -4452,6 +4452,34 @@ public static C GetC() await TestRefactoringAsync(initialMarkup, changedMarkup); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72032")] + public async Task TestConstructorWithoutBody() + { + var initialMarkup = """ + namespace N + { + public class [|C|] + { + public int P { get; private set; } + + public extern C(); + } + } + """; + var fixedMarkup = """ + namespace N + { + public record [|C|](int P) + { + public int P { get; private set; } = P; + + public extern C(); + } + } + """; + await TestRefactoringAsync(initialMarkup, fixedMarkup); + } + #region selection [Fact] diff --git a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs index 4399e7d706c12..10318c3aa9de5 100644 --- a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs +++ b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs @@ -49,7 +49,7 @@ static void Main(string[] args) var active = GetActiveStatements(src1, src2); EditAndContinueValidation.VerifySemantics( - new[] { edits }, + [edits], [ DocumentResults( active, @@ -281,7 +281,7 @@ static void Swap(T lhs, T rhs) where T : System.IComparable edits.VerifySemantics( active, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Swap"), preserveLocalVariables: true) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Swap"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -488,7 +488,7 @@ static void Main(string[] args) edits.VerifySemantics( active, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), syntaxMap[0])]); } [Fact] @@ -572,7 +572,7 @@ public void Method_Partial_SignatureChangeInsertDelete1() var srcB2 = "partial class C { void F(byte x) {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( activeStatements: GetActiveStatements(srcA1, srcA2), @@ -595,7 +595,7 @@ public void Method_Partial_SignatureChangeInsertDelete2() var srcB2 = "partial class C { void F(byte x) {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( activeStatements: GetActiveStatements(srcA1, srcA2), @@ -774,11 +774,10 @@ public void Property_BlockBodyToExpressionBody2() var active = GetActiveStatements(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -860,12 +859,11 @@ public void Indexer_BlockBodyToExpressionBody2() var active = GetActiveStatements(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -939,7 +937,7 @@ public T this[int i] capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics(active, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -1043,7 +1041,7 @@ public T this[int i] capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics(active, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -1145,7 +1143,7 @@ public T this[int i] capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics(active, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -1245,7 +1243,7 @@ public T this[int i] capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics(active, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } diff --git a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs index 71cf7efd601d3..3ed08b00727ff 100644 --- a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs @@ -261,11 +261,11 @@ static void Goo(int a) var active = GetActiveStatements(src1, src2); edits.VerifySemantics(active, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Goo"), preserveLocalVariables: true) - }); + ]); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/846588")] @@ -865,7 +865,7 @@ public void Parameter_Update_RefKind_RuntimeTypeUnchanged( // Having compiler-generated attributes visible via Reflaction API is not that important. // The same for [in] and [out] metadata flags. edits.VerifySemantics(active, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.Baseline); } @@ -885,7 +885,7 @@ public void Parameter_Update_Modifiers_RuntimeTypeUnchanged(string newModifiers) // Having compiler-generated attributes visible via Reflaction API is not that important. // The same for [in] and [out] metadata flags. edits.VerifySemantics(active, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.Baseline); } @@ -1085,10 +1085,9 @@ class Goo edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Goo..ctor"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueTestHelpers.Net6RuntimeCapabilities); } @@ -1625,8 +1624,7 @@ public C(int a) {} edits.VerifySemanticDiagnostics(active); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68708")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")] public void Constructor_Instance_ImplicitInitializer_ParameterChange() { var src1 = "class C { C(int P) {} }"; @@ -2524,8 +2522,7 @@ static void Main(string[] args) edits.VerifySemanticDiagnostics(active); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69249")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69249")] public void InstanceFieldInitializer_Internal_Delete2() { var src1 = @" @@ -3205,13 +3202,12 @@ class C var active = GetActiveStatements(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.a")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_a"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.a"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11732,14 +11728,14 @@ public void InsertDeleteMethod_Inactive() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( activeStatements: GetActiveStatements(srcA1, srcA2, documentIndex: 0), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F2")), - }), + ]), DocumentResults( activeStatements: GetActiveStatements(srcB1, srcB2, documentIndex: 1)) ]); @@ -11758,14 +11754,14 @@ public void InsertDeleteMethod_Active() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2, documentIndex: 0), GetTopEdits(srcB1, srcB2, documentIndex: 1) }, + [GetTopEdits(srcA1, srcA2, documentIndex: 0), GetTopEdits(srcB1, srcB2, documentIndex: 1)], [ DocumentResults( activeStatements: GetActiveStatements(srcA1, srcA2, documentIndex: 0), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")), - }), + ]), DocumentResults( activeStatements: GetActiveStatements(srcB1, srcB2, documentIndex: 1), diagnostics: [Diagnostic(RudeEditKind.DeleteActiveStatement, "partial class C", GetResource("method", "F()"))]) @@ -11781,14 +11777,14 @@ public void InsertDeleteMethod_Active_EntirePartialTypeDeclaration() var srcB2 = ""; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2, documentIndex: 0), GetTopEdits(srcB1, srcB2, documentIndex: 1) }, + [GetTopEdits(srcA1, srcA2, documentIndex: 0), GetTopEdits(srcB1, srcB2, documentIndex: 1)], [ DocumentResults( activeStatements: GetActiveStatements(srcA1, srcA2, documentIndex: 0), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")), - }), + ]), DocumentResults( activeStatements: GetActiveStatements(srcB1, srcB2, documentIndex: 1), diagnostics: [Diagnostic(RudeEditKind.DeleteActiveStatement, "", GetResource("method", "C.F()"))]) @@ -12314,7 +12310,7 @@ public static void H(int x) : Diagnostic(RudeEditKind.MemberBodyInternalError, "public static void G()", "G", SimpleToStringException.ToStringOutput); validator.VerifySemantics( - new[] { edits }, + [edits], TargetFramework.NetCoreApp, [DocumentResults(diagnostics: [expectedDiagnostic])]); } diff --git a/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs b/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs index e9bff311b20b8..f8f0e283a7325 100644 --- a/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/LineEditTests.cs @@ -184,7 +184,7 @@ void F() var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"))]); } [Fact] @@ -389,7 +389,7 @@ class C { /*--*/static void Bar() { } }"; var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"))]); } [Fact] @@ -442,7 +442,7 @@ static void Bar() var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"))]); } [Fact] @@ -472,14 +472,14 @@ static void Bar() var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"))]); var active = GetActiveStatements(src1, src2); var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( active, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"), syntaxMap[0])]); } [Fact] @@ -539,7 +539,7 @@ static void Bar() edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"))], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -572,7 +572,7 @@ static void Bar() edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar")) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"))], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -602,11 +602,10 @@ static async Task Bar() var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Bar"), preserveLocalVariables: true)]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69027")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69027")] public void Method_StackAlloc_LineChange() { var src1 = @" @@ -633,8 +632,7 @@ void F() new[] { new SourceLineUpdate(5, 6) }); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69027")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69027")] public void Method_StackAlloc_Recompile() { var src1 = @" @@ -669,8 +667,7 @@ void F() [Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc bool[64]", GetResource("method"))]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69027")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69027")] public void Method_StackAlloc_NonActive() { var src1 = @" @@ -728,7 +725,7 @@ void F() edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)]); } #endregion @@ -818,7 +815,7 @@ public C(int a var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)]); } @@ -950,7 +947,7 @@ class C(int a); var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true)]); } @@ -966,7 +963,7 @@ class C(int a ); var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true)]); } @@ -982,11 +979,11 @@ record C(int P); var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -1001,10 +998,10 @@ record C(int P ); var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true) - }); + ]); } @@ -1020,13 +1017,13 @@ record C( int P); var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -1041,14 +1038,14 @@ record C(int P); var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -1101,7 +1098,7 @@ public C(int a) var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)]); } [Fact] @@ -1158,7 +1155,7 @@ public C(int a) edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -1233,7 +1230,7 @@ public C(int a) var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)]); } #endregion @@ -1410,10 +1407,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1456,10 +1453,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1481,10 +1478,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1505,10 +1502,10 @@ static int Goo var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1529,10 +1526,10 @@ static int var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1553,10 +1550,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1577,10 +1574,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1600,10 +1597,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -1629,10 +1626,10 @@ class C edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -1655,10 +1652,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1684,7 +1681,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod)]); } [Fact] @@ -1825,7 +1822,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( lineEdits: new[] { new SourceLineUpdate(3, 4) }, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"))]); } [Fact] @@ -1848,7 +1845,7 @@ int P var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( lineEdits: new[] { new SourceLineUpdate(3, 5) }, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"))]); } [Fact] @@ -1868,7 +1865,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)]); } #endregion @@ -1893,7 +1890,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").GetMethod) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").GetMethod)]); } [Fact] @@ -2097,7 +2094,7 @@ event Action E { add { } remove var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod)]); } [Fact] @@ -2119,7 +2116,7 @@ event Action E { add { } remove { var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod)]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/53263")] @@ -2141,7 +2138,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifyLineEdits( new[] { new SourceLineUpdate(3, 4) }, - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod)]); } [Fact] @@ -2244,7 +2241,7 @@ static void F() // Line deltas can't be applied on the whole breakpoint span hence recompilation. edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) }); + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"))]); } /// @@ -2300,11 +2297,11 @@ void F4() {} new SourceLineUpdate(6, 6), // lines between F2 and D ctor new SourceLineUpdate(9, 19))) // D ctor }, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.F3")), // overlaps with "void F1() { }" SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.F4")), // overlaps with "void F2() { }" - }); + ]); } [Fact] @@ -2407,10 +2404,10 @@ static void F() { new("a", ImmutableArray.Create(new SourceLineUpdate(6, 4))), }, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }); + ]); } [Fact] @@ -2436,10 +2433,10 @@ class C { static void F() { } }"; edits.VerifyLineEdits( Array.Empty(), - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }, + ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } diff --git a/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs b/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs index 3eb5efdae37d8..e060c80f69f0f 100644 --- a/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs @@ -2010,7 +2010,7 @@ public void Lambdas_AddAttribute() capabilities: EditAndContinueCapabilities.Baseline); GetTopEdits(edits).VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -3713,10 +3713,10 @@ void F() edits.VerifySemantics( ActiveStatementsDescription.Empty, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMembers("F").Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -4315,7 +4315,7 @@ partial class C }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( semanticEdits: [ @@ -4702,8 +4702,7 @@ event Action D SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.remove_D"))); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Lambdas_Update_CeaseCapture_ConstructorInitializer_This() { var src1 = "class C { C(int x) : this(() => x) {} C(Func f) {} }"; @@ -4714,8 +4713,7 @@ public void Lambdas_Update_CeaseCapture_ConstructorInitializer_This() SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.Parameters is [{ Name: "x" }]), preserveLocalVariables: true)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Lambdas_Update_CeaseCapture_ConstructorInitializer_Base() { var src1 = "class C : B { C(int x) : base(() => x) {} } class B { public B(Func f) {} }"; @@ -5225,8 +5223,7 @@ void F() SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Lambdas_Update_Capturing_ConstructorInitializer_This() { var src1 = "class C { C(int x) : this(() => 1) {} C(Func f) {} }"; @@ -5238,8 +5235,7 @@ public void Lambdas_Update_Capturing_ConstructorInitializer_This() capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Lambdas_Update_Capturing_ConstructorInitializer_Base() { var src1 = "class C : B { C(int x) : base(() => 1) {} } class B { public B(Func f) {} }"; @@ -5340,8 +5336,7 @@ public void Lambdas_Update_Capturing_PrimaryParameter_Method_PrimaryToThisCaptur SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"), preserveLocalVariables: true)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69152")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69152")] public void Lambdas_Update_PrimaryParameterOutsideOfLambda() { var src1 = @" @@ -5447,8 +5442,7 @@ partial void F() // impl SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").PartialImplementationPart, preserveLocalVariables: true, partialType: "C")); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69152")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69152")] public void Lambdas_Update_StaticToPrimaryParameterOnly_Partial() { var src1 = @" @@ -5526,8 +5520,7 @@ void F() SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69152")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69152")] public void Lambdas_Update_StaticToPrimaryParameterOnly3() { var src1 = @" @@ -6292,8 +6285,7 @@ class B(Func f); capabilities: EditAndContinueCapabilities.UpdateParameters); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68708")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")] public void Lambdas_CapturedParameter_ChangeType() { var src1 = @" @@ -6419,10 +6411,9 @@ static void Main(int y, int x) edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.Main"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueTestHelpers.Net6RuntimeCapabilities); } @@ -11202,7 +11193,7 @@ static IEnumerable F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11252,7 +11243,7 @@ static IEnumerable F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11305,7 +11296,7 @@ static IEnumerable F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11694,7 +11685,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11722,7 +11713,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11744,7 +11735,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11766,7 +11757,7 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11794,7 +11785,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11822,7 +11813,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11849,7 +11840,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11877,7 +11868,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11905,7 +11896,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11932,7 +11923,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11960,7 +11951,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -12015,7 +12006,7 @@ static async IEnumerable F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -12146,7 +12137,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -12174,7 +12165,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -12204,7 +12195,7 @@ static async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -12243,7 +12234,7 @@ static async IAsyncEnumerable F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } diff --git a/src/Features/CSharpTest/EditAndContinue/SyntaxComparerTests.cs b/src/Features/CSharpTest/EditAndContinue/SyntaxComparerTests.cs index 8f291d192482c..b2fcacdfb43b5 100644 --- a/src/Features/CSharpTest/EditAndContinue/SyntaxComparerTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/SyntaxComparerTests.cs @@ -24,16 +24,16 @@ private static SyntaxNode MakeLiteral(int n) public void GetSequenceEdits1() { var edits = SyntaxComparer.GetSequenceEdits( - new[] { MakeLiteral(0), MakeLiteral(1), MakeLiteral(2) }, - new[] { MakeLiteral(1), MakeLiteral(3) }); + [MakeLiteral(0), MakeLiteral(1), MakeLiteral(2)], + [MakeLiteral(1), MakeLiteral(3)]); - AssertEx.Equal(new[] - { + AssertEx.Equal( + [ new SequenceEdit(2, -1), new SequenceEdit(-1, 1), new SequenceEdit(1, 0), new SequenceEdit(0, -1), - }, edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); + ], edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); } [Fact] @@ -43,29 +43,29 @@ public void GetSequenceEdits2() ImmutableArray.Create(MakeLiteral(0), MakeLiteral(1), MakeLiteral(2)), ImmutableArray.Create(MakeLiteral(1), MakeLiteral(3))); - AssertEx.Equal(new[] - { + AssertEx.Equal( + [ new SequenceEdit(2, -1), new SequenceEdit(-1, 1), new SequenceEdit(1, 0), new SequenceEdit(0, -1), - }, edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); + ], edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); } [Fact] public void GetSequenceEdits3() { var edits = SyntaxComparer.GetSequenceEdits( - new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword) }, - new[] { SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword) }); + [SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)], + [SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)]); - AssertEx.Equal(new[] - { + AssertEx.Equal( + [ new SequenceEdit(2, 2), new SequenceEdit(1, -1), new SequenceEdit(0, 1), new SequenceEdit(-1, 0), - }, edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); + ], edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); } [Fact] @@ -75,21 +75,21 @@ public void GetSequenceEdits4() ImmutableArray.Create(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)), ImmutableArray.Create(SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword))); - AssertEx.Equal(new[] - { + AssertEx.Equal( + [ new SequenceEdit(2, 2), new SequenceEdit(1, -1), new SequenceEdit(0, 1), new SequenceEdit(-1, 0), - }, edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); + ], edits, itemInspector: e => e.GetTestAccessor().GetDebuggerDisplay()); } [Fact] public void ComputeDistance_Nodes() { var distance = SyntaxComparer.ComputeDistance( - new[] { MakeLiteral(0), MakeLiteral(1), MakeLiteral(2) }, - new[] { MakeLiteral(1), MakeLiteral(3) }); + [MakeLiteral(0), MakeLiteral(1), MakeLiteral(2)], + [MakeLiteral(1), MakeLiteral(3)]); Assert.Equal(0.67, Math.Round(distance, 2)); } @@ -98,8 +98,8 @@ public void ComputeDistance_Nodes() public void ComputeDistance_Tokens() { var distance = SyntaxComparer.ComputeDistance( - new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword) }, - new[] { SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword) }); + [SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)], + [SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.AsyncKeyword)]); Assert.Equal(0.33, Math.Round(distance, 2)); } diff --git a/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs index fc4ccc915730a..1eac532fdd3bb 100644 --- a/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs @@ -504,7 +504,7 @@ void M2() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("N.C.M2")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("N.C.M2"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -664,7 +664,7 @@ public void Type_Kind_Update_Reloadable(string oldKeyword, string newKeyword) "Update [[CreateNewOnMetadataUpdate]" + oldKeyword + " C { }]@145 -> [[CreateNewOnMetadataUpdate]" + newKeyword + " C { }]@145"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -720,7 +720,7 @@ public void Type_Modifiers_Accessibility_Partial(string accessibilityA, string a var srcB2 = accessibilityB + " partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults(), @@ -759,7 +759,7 @@ public void Type_Modifiers_Accessibility_Reloadable() "Update [[CreateNewOnMetadataUpdate]public class C { }]@145 -> [[CreateNewOnMetadataUpdate]internal class C { }]@145"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -879,13 +879,13 @@ public void Type_Modifiers_Unsafe_DeleteInsert() var srcB2 = "partial class C { void F() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")) - }), + ]), ]); } @@ -1040,7 +1040,7 @@ public void Type_Attribute_Update_InlineArray_Reloadable(string keyword) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1134,8 +1134,7 @@ public void Type_Attribute_Delete_InlineArray(string keyword) capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1831006")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1831006")] public void Type_Attribute_Update_Null() { var attribute = @" @@ -1149,7 +1148,7 @@ public class A : Attribute { public A1(int[] array, Type type, Type[] types) {} var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C")) }, + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -1171,7 +1170,7 @@ public class A3 : System.Attribute { } "Update [[CreateNewOnMetadataUpdate, A1, A2]class C { }]@267 -> [[CreateNewOnMetadataUpdate, A2, A3]class C { }]@267"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1184,7 +1183,7 @@ public void Type_Attribute_ReloadableRemove() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1198,7 +1197,7 @@ public void Type_Attribute_ReloadableAdd() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -1211,7 +1210,7 @@ public void Type_Attribute_ReloadableBase() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1234,7 +1233,7 @@ class B : System.Attribute { } edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -1254,16 +1253,16 @@ class B : System.Attribute { } var srcB2 = "[B]partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1738,7 +1737,7 @@ interface I {} interface J {}"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC, srcC) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC, srcC)], [ DocumentResults(), DocumentResults(), @@ -1758,7 +1757,7 @@ public void Type_Base_Partial_InsertDeleteAndUpdate() var srcC2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), @@ -1783,7 +1782,7 @@ interface I {} interface J {}"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC, srcC) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC, srcC)], [ DocumentResults(), DocumentResults(), @@ -1870,7 +1869,7 @@ public void Type_Insert_Reloadable() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -1961,7 +1960,7 @@ public void Struct_Modifiers_Partial_InsertDelete(string modifier) var srcB2 = modifier + " partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults() @@ -2147,15 +2146,15 @@ static void M() { } } "; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("M")) - }), + ]), ]); } @@ -2337,7 +2336,7 @@ class D {} "; var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -2355,25 +2354,25 @@ interface I { void F() {} } var srcB2 = srcA1; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("S")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("S.F")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I.F")) - }) + ]) ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), @@ -2436,19 +2435,19 @@ public void Type_Partial_DeleteDeclaration() var srcB2 = "partial class C { void G() {} void M() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("M")), - }) + ]) ]); } @@ -2459,7 +2458,7 @@ public void Type_Partial_InsertFirstDeclaration() var src2 = "partial class C { void F() {} }"; GetTopEdits(src1, src2).VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"), preserveLocalVariables: false) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"), preserveLocalVariables: false)], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -2472,15 +2471,15 @@ public void Type_Partial_InsertSecondDeclaration() var srcB2 = "partial class C { void G() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("G"), preserveLocalVariables: false) - }), + ]), ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -2494,14 +2493,14 @@ public void Type_Partial_Reloadable() var srcB2 = "partial class C { void G() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -2520,17 +2519,17 @@ interface I { void F() {} } var srcB2 = srcA1; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("S").GetMember("F")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("F")), - }) + ]) ]); } @@ -2544,14 +2543,14 @@ public void Type_DeleteInsert_Reloadable() var srcB2 = "[CreateNewOnMetadataUpdate]class C { void F() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")), - }) + ]) ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -2581,20 +2580,20 @@ void F() {} // TODO: The methods without bodies do not need to be updated. EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("AbstractMethod")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("VirtualMethod")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("ToString")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("I.G")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("G")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("F")), - }) + ]) ]); } @@ -2635,20 +2634,20 @@ void F() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("AbstractMethod")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("VirtualMethod")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("ToString")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("I.G")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("G")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("F")), - }) + ]) ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -2678,17 +2677,17 @@ class C } "; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true), - }) + ]) ]); } @@ -2719,17 +2718,17 @@ partial class C } "; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true), - }) + ]) ]); } @@ -2762,15 +2761,15 @@ class C "; // note that accessors are not updated since they do not have bodies EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true), - }), + ]), DocumentResults() ]); @@ -2858,7 +2857,7 @@ public void Type_Move_MultiFile() "Move [class C {}]@41 -> @14"); EditAndContinueValidation.VerifySemantics( - new[] { editsA, editsB }, + [editsA, editsB], [ DocumentResults(), DocumentResults(), @@ -2881,7 +2880,7 @@ public void Record_Insert() "Insert [record C;]@0"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -2894,7 +2893,7 @@ public void Record_Insert_WithParameters() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -3110,10 +3109,9 @@ public void Record_Method_Insert_ReplacingSynthesizedWithCustom_ParameterNameCha capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => methodName switch { ".ctor" => c.GetCopyConstructor("C"), "Equals" => c.GetSpecializedEqualsOverload("C"), _ => c.GetMember("C." + methodName) }), - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -3137,10 +3135,9 @@ public void Record_Method_Insert_ReplacingSynthesizedWithCustom_SemanticError() capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("C.PrintMembers").First().ISymbol), - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -3204,10 +3201,9 @@ public void Record_Method_Delete_ReplacingSynthesizedWithCustom_ParameterNameCha capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => methodName switch { ".ctor" => c.GetCopyConstructor("C"), "Equals" => c.GetSpecializedEqualsOverload("C"), _ => c.GetMember("C." + methodName) }), - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -3239,14 +3235,13 @@ public void Record_Field_Insert() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C._y")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3273,13 +3268,12 @@ public C(C other) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C._y")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3293,15 +3287,14 @@ public void Record_Field_Insert_WithInitializer() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C._y")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3315,14 +3308,13 @@ public void Record_Field_Insert_WithExistingInitializer() var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C._z")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3336,15 +3328,14 @@ public void Record_Field_Insert_WithInitializerAndExistingInitializer() var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C._z")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), syntaxMap[0]), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3394,8 +3385,7 @@ public void Record_Property_Delete_Writable(string setter) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3403,7 +3393,7 @@ public void Record_Property_Delete_Writable(string setter) SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -3418,15 +3408,14 @@ public void Record_Property_Delete_ReadOnly(string getter) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -3488,11 +3477,10 @@ public void Record_Property_Delete_WriteOnly() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -3505,12 +3493,11 @@ public void Record_Property_Delete_Static() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -3534,8 +3521,7 @@ public C(bool b) : this(1) { } var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3544,7 +3530,7 @@ public C(bool b) : this(1) { } SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -3612,12 +3598,12 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_Auto_Partial(s var srcB2 = "partial record C;"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3625,7 +3611,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_Auto_Partial(s SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType: "C", preserveLocalVariables: true) - }) + ]) ]); } @@ -3643,8 +3629,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithBody(strin // Methods using backing field must be updated, unless they are explicitly declared. edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3652,7 +3637,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithBody(strin SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.X").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.X").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3713,12 +3698,12 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithBody_Parti // Methods using backing field must be updated, unless they are explicitly declared. EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3726,7 +3711,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithBody_Parti SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.X").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.X").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType : "C", preserveLocalVariables: true), - }) + ]) ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -3741,8 +3726,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithAttribute( edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3751,7 +3735,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithAttribute( SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -3769,8 +3753,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithAttributeO edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -3778,7 +3761,7 @@ public void Record_Property_Delete_ReplacingCustomWithSynthesized_WithAttributeO SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -3812,14 +3795,13 @@ public void Record_Property_Insert(string accessors) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -3832,10 +3814,9 @@ public void Record_Property_Insert_WriteOnly() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -3848,10 +3829,9 @@ public void Record_Property_Insert_Static() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")) - }, + ], capabilities: EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -3875,15 +3855,14 @@ public C(bool b) : this(1) { } var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -3909,15 +3888,15 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithSetter_Wri var edits = GetTopEdits(src1, src2); - edits.VerifySemantics(new[] - { + edits.VerifySemantics( + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -3929,8 +3908,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_ReadOnly() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_X"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), @@ -3938,7 +3916,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_ReadOnly() SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -3952,15 +3930,15 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_TypeLayoutChan // Note: We do not report rude edits when a synthesized auto-property is replaced by an explicit one. // The synthesized property accessors are updated to throw and the backing field remains in the type. // The deleted field will remain unused since adding the primary property back is a rude edit. - edits.VerifySemantics(new[] - { + edits.VerifySemantics( + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -4016,10 +3994,9 @@ public C(C original) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -4059,12 +4036,12 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_Auto_Partial(s var srcB2 = "partial record C { public int X { get; init; }" + initializer + " }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -4072,7 +4049,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_Auto_Partial(s SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType: "C", preserveLocalVariables: true) - }) + ]) ]); } @@ -4110,12 +4087,12 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithBody_Parti var srcB2 = "partial record C { public int X { " + body + " } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -4123,7 +4100,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithBody_Parti SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_X")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType: "C", preserveLocalVariables: true) - }) + ]) ]); } @@ -4137,8 +4114,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithAttribute( edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -4147,7 +4123,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithAttribute( SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -4165,8 +4141,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithAttributeO edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -4174,7 +4149,7 @@ public void Record_Property_Insert_ReplacingSynthesizedWithCustom_WithAttributeO SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -4192,15 +4167,15 @@ public void Record_Property_DeleteInsert() var srcB2 = "partial record C { public int Y { get; init; } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Y").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Y").SetMethod) - }), + ]), ]); } @@ -4325,12 +4300,12 @@ public void Enum_Member_Attribute_InsertDeleteAndUpdate() var srcB2 = ""; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("N.A")) - }), + ]), DocumentResults() ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); @@ -4499,7 +4474,7 @@ public void EnumInitializerUpdate_Reloadable() edits.VerifyEdits("Update [Red = 1]@185 -> [Red = 2]@185"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("Color")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("Color"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -4822,12 +4797,11 @@ public void Delegate_ReturnType_Update_RuntimeTypeUnchanged() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.Invoke")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.EndInvoke")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -4845,12 +4819,11 @@ public void Delegate_ReturnType_AddAttribute() "Update [public delegate int D(int a);]@39 -> [[return: A]public delegate int D(int a);]@39"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.Invoke")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.EndInvoke")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -4878,7 +4851,7 @@ public void Delegate_Parameter_Insert_Reloadable() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("D")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("D"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -4913,11 +4886,10 @@ public void Delegate_Parameter_Rename() capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.Invoke")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.BeginInvoke")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -4964,11 +4936,10 @@ public void Delegate_Parameter_Update_Attribute() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.Invoke")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.BeginInvoke")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -5131,7 +5102,7 @@ public void Delegate_Attribute_Add() "Update [public delegate int D(int a);]@48 -> [[A]public delegate int D(int a);]@48"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -5149,12 +5120,11 @@ public void Delegate_Attribute_Add_WithReturnTypeAttribute() "Update [public delegate int D(int a);]@39 -> [[return: A][A]public delegate int D(int a);]@39"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.Invoke")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D.EndInvoke")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("D")), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -5252,16 +5222,16 @@ public void NestedType_Replace_WithUpdateInNestedType_Partial_DifferentDocument( var editsB = GetTopEdits(srcB1, srcB2); EditAndContinueValidation.VerifySemantics( - new[] { editsA, editsB }, + [editsA, editsB], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.D.M")) - }) + ]) ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5276,11 +5246,11 @@ public void NestedType_Replace_WithUpdateInNestedType_Partial_SameDocument() EditAndContinueValidation.VerifySemantics( edits, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.D.M")) - }, + ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5294,11 +5264,11 @@ public void NestedType_Replace_WithUpdateInNestedType() EditAndContinueValidation.VerifySemantics( edits, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.D.M")) - }, + ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5312,11 +5282,11 @@ public void NestedType_Update_WithUpdateInNestedType() EditAndContinueValidation.VerifySemantics( edits, - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.D.M")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -5397,7 +5367,7 @@ public void NestedType_Move_MultiFile() "Move [class C {}]@49 -> @18"); EditAndContinueValidation.VerifySemantics( - new[] { editsA, editsB }, + [editsA, editsB], [ DocumentResults(), DocumentResults(), @@ -5505,7 +5475,7 @@ public void NestedType_Insert_ReloadableIntoReloadable1() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5518,7 +5488,7 @@ public void NestedType_Insert_ReloadableIntoReloadable2() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5531,7 +5501,7 @@ public void NestedType_Insert_ReloadableIntoReloadable3() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5556,7 +5526,7 @@ public void NestedType_Insert_Member_Reloadable() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C.D")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C.D"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -5577,10 +5547,10 @@ private class D }"; var edits = GetTopEdits(src1, src2); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.D"), preserveLocalVariables: false) - }); + ]); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/835827")] @@ -5692,10 +5662,10 @@ public void NestedType_MethodDeleteInsert() "Delete [()]@32"); edits.VerifySemantics( - new[] { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.D")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -5772,7 +5742,7 @@ public void NestedEnumInPartialType_InsertDelete() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults() @@ -5788,7 +5758,7 @@ public void NestedEnumInPartialType_InsertDeleteAndUpdateMember() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -5809,7 +5779,7 @@ public void NestedEnumInPartialType_InsertDeleteAndUpdateBase() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -5830,7 +5800,7 @@ public void NestedEnumInPartialType_InsertDeleteAndInsertMember() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: [Diagnostic(RudeEditKind.Insert, "B = 2", FeaturesResources.enum_value)]), @@ -5848,7 +5818,7 @@ public void NestedDelegateInPartialType_InsertDelete() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( // delegate does not have any user-defined method body and this does not need a PDB update @@ -5867,7 +5837,7 @@ public void NestedDelegateInPartialType_InsertDeleteAndChangeParameters() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: [Diagnostic(RudeEditKind.TypeUpdate, "delegate void D(int x)", GetResource("delegate"))]), @@ -5885,7 +5855,7 @@ public void NestedDelegateInPartialType_InsertDeleteAndChangeReturnType() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -5906,7 +5876,7 @@ public void NestedDelegateInPartialType_InsertDeleteAndChangeOptionalParameterVa var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -5930,18 +5900,18 @@ public void NestedPartialTypeInPartialType_InsertDeleteAndChange() var srcC2 = "partial struct S { partial class C { void F2(int x) {} } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("S.C.F2").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Byte))?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("S.C")) - }), + ]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("S.C.F2").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Int32))?.ISymbol) }) + semanticEdits: [SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("S.C.F2").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Int32))?.ISymbol)]) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -5956,16 +5926,16 @@ public void Type_Insert_Partial_Multiple() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"), partialType: "C") - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -6000,13 +5970,13 @@ public void Type_Partial_InsertDeleteAndChange_Attribute() var srcC2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C"), partialType: "C") - }), + ]), DocumentResults(), ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); @@ -6024,7 +5994,7 @@ public void Type_Partial_InsertDeleteAndChange_TypeParameterAttribute() var srcC2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), @@ -6039,7 +6009,7 @@ public void Type_Partial_InsertDeleteAndChange_TypeParameterAttribute() capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), @@ -6066,7 +6036,7 @@ public void Type_Partial_InsertDeleteAndChange_Constraint() var srcC2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), @@ -6096,16 +6066,16 @@ public void Type_Partial_InsertDeleteRefactor() var srcE = "interface I {} interface J {}"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2), GetTopEdits(srcE, srcE) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2), GetTopEdits(srcE, srcE)], [ DocumentResults(), DocumentResults(), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F"))]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("G")) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("G"))]), DocumentResults(), ]); @@ -6126,16 +6096,16 @@ class B : System.Attribute {} var srcB2 = "[B]partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C"), partialType: "C") - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -6154,18 +6124,18 @@ public void Type_Partial_InsertDeleteRefactor_AttributeListSplitting() var srcD2 = "[B]partial class C { void G() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2)], [ DocumentResults(), DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.G")) - }), + ]), ]); } @@ -6181,7 +6151,7 @@ public void Type_Partial_InsertDeleteChangeMember() var srcC2 = "partial class C { void F(int y = 2) { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), DocumentResults(diagnostics: [Diagnostic(RudeEditKind.InitializerUpdate, "int x = 2", FeaturesResources.parameter)]), @@ -6207,7 +6177,7 @@ public void NestedPartialTypeInPartialType_InsertDeleteAndInsertVirtual() var srcF2 = "partial interface I { partial class C { virtual void N2() {} } }"; // insert new virtual into new partial decl EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2), GetTopEdits(srcE1, srcE2), GetTopEdits(srcF1, srcF2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2), GetTopEdits(srcE1, srcE2), GetTopEdits(srcF1, srcF2)], [ // A DocumentResults(), @@ -6217,7 +6187,7 @@ public void NestedPartialTypeInPartialType_InsertDeleteAndInsertVirtual() // C DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("C").GetMember("F1")) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("C").GetMember("F1"))]), // D DocumentResults( @@ -6225,7 +6195,7 @@ public void NestedPartialTypeInPartialType_InsertDeleteAndInsertVirtual() // E DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("C").GetMember("F2")) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("C").GetMember("F2"))]), // F DocumentResults( @@ -6365,7 +6335,7 @@ public void Namespace_Insert_NewType(string src2) capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("N.C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("N.C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -6382,7 +6352,7 @@ public void Namespace_Insert_NewType_Qualified(string src2) capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("N.M.C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("N.M.C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -6655,18 +6625,18 @@ public void Namespace_Update_MultiplePartials1() var srcB2 = @"namespace M { partial class/*3*/C {} } namespace N { partial class/*4*/C {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("M.C"), partialType: "M.C"), - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("M.C"), partialType: "M.C"), - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -6680,7 +6650,7 @@ public void Namespace_Update_MultiplePartials2() var srcB2 = @"namespace M { partial class/*3*/C {} } namespace M { partial class/*4*/C {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(diagnostics: [ @@ -6895,11 +6865,11 @@ event Action E { add {} remove {} } "Delete [F2]@284"); EditAndContinueValidation.VerifySemantics( - new[] { edits }, + [edits], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P1").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P1").SetMethod), @@ -6913,7 +6883,7 @@ event Action E { add {} remove {} } SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("C.this[]").Single(m => m.Parameters[0].Type.Name == "Byte")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").AddMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E").RemoveMethod), - }) + ]) ]); } @@ -6926,13 +6896,13 @@ public void PartialMember_InsertDelete_MultipleDocuments() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F"), preserveLocalVariables: false) - }), + ]), DocumentResults() ]); @@ -6947,15 +6917,15 @@ public void PartialMember_DeleteInsert_MultipleDocuments() var srcB2 = "partial class C { void F() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }) + ]) ]); } @@ -6968,18 +6938,18 @@ public void PartialMember_DeleteInsert_GenericMethod() var srcB2 = "partial class C { void F() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }) + ]) ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults(diagnostics: @@ -6999,18 +6969,18 @@ public void PartialMember_DeleteInsert_GenericType() var srcB2 = "partial class C { void F() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }) + ]) ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults(diagnostics: @@ -7030,15 +7000,15 @@ public void PartialMember_DeleteInsert_Destructor() var srcB2 = "partial class C { ~C() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("Finalize"), preserveLocalVariables: false), - }) + ]) ]); } @@ -7052,7 +7022,7 @@ public void PartialNestedType_InsertDeleteAndChange() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -7073,18 +7043,18 @@ public void PartialMember_RenameInsertDelete() var srcB2 = "partial class C { void F1() {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F2")), - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F1")), - }) + ]) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -7132,7 +7102,7 @@ public void PartialMember_SignatureChangeInsertDelete() var srcB2 = "partial class C { void F(byte x) {} }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("C.F").Single(m => m.Parameters is [{ Type.SpecialType: SpecialType.System_Char }]))]), @@ -7151,7 +7121,7 @@ public void PartialMember_SignatureChangeInsertDelete_Indexer() var srcB2 = "partial class C { int this[byte y] { get => 1; set {} } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(semanticEdits: [ @@ -7206,13 +7176,13 @@ partial class C "; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) - }) + ]) ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -7227,14 +7197,14 @@ public void PartialMember_DeleteInsert_UpdatePropertyAccessors() var srcB2 = "partial class C { int P { get => 2; set { Console.WriteLine(2); } } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod) - }) + ]) ]); } @@ -7248,13 +7218,13 @@ public void PartialMember_DeleteInsert_UpdateAutoProperty() var srcB2 = "partial class C { int P => 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod) - }) + ]) ]); } @@ -7268,13 +7238,13 @@ public void PartialMember_DeleteInsert_AddFieldInitializer() var srcB2 = "partial class C { int f = 1; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }) + ]) ]); } @@ -7288,13 +7258,13 @@ public void PartialMember_DeleteInsert_RemoveFieldInitializer() var srcB2 = "partial class C { int f; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }) + ]) ]); } @@ -7308,13 +7278,13 @@ public void PartialMember_DeleteInsert_ConstructorWithInitializers() var srcB2 = "partial class C { C(int x) { f = x + 1; } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true) - }) + ]) ]); } @@ -7327,19 +7297,19 @@ public void PartialMember_DeleteInsert_MethodAddParameter() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetParameterCount() == 1)?.ISymbol) - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetParameterCount() == 0)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("S")) - }), + ]), ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -7353,19 +7323,19 @@ public void PartialMember_DeleteInsert_UpdateMethodParameterType() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Byte))?.ISymbol) - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Int32))?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("S")) - }), + ]), ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -7379,19 +7349,19 @@ public void PartialMember_DeleteInsert_MethodAddTypeParameter() var srcB2 = "partial struct S { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetArity() == 1)?.ISymbol) - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("S.F").FirstOrDefault(m => m.GetArity() == 0)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("S")) - }), + ]), ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.GenericAddMethodToExistingType); } @@ -7622,11 +7592,10 @@ public void Method_Update_ReturnType_RuntimeTypeChanged(string oldType, string n var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -7643,11 +7612,10 @@ public void Method_Update_ReturnType_WithBodyChange() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -7667,11 +7635,10 @@ public void Method_Update_ReturnType_Tuple() "Update [(int, int) M() { throw new System.Exception(); }]@10 -> [(string, int) M() { throw new System.Exception(); }]@10"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -7691,11 +7658,10 @@ public void Method_Update_ReturnType_Tuple_ElementDelete() "Update [(int, int, int a) M() { return (1, 2, 3); }]@10 -> [(int, int) M() { return (1, 2); }]@10"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -7715,11 +7681,10 @@ public void Method_Update_ReturnType_Tuple_ElementAdd() "Update [(int, int) M() { return (1, 2); }]@10 -> [(int, int, int a) M() { return (1, 2, 3); }]@10"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -7770,7 +7735,7 @@ static void Main(string[] args) edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), preserveLocalVariables: false) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), preserveLocalVariables: false)]); } [Fact] @@ -7798,7 +7763,7 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), preserveLocalVariables: false) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main"), preserveLocalVariables: false)]); } [Fact] @@ -7811,10 +7776,10 @@ public void MethodWithExpressionBody_ToBlockBody() edits.VerifyEdits("Update [static int F(int a) => 1;]@10 -> [static int F(int a) { return 2; }]@10"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -7827,10 +7792,10 @@ public void MethodWithBlockBody_ToExpressionBody() edits.VerifyEdits("Update [static int F(int a) { return 2; }]@10 -> [static int F(int a) => 1;]@10"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -7866,7 +7831,7 @@ static void F() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap[0])]); } [Fact] @@ -7925,7 +7890,7 @@ class C "Delete [()]@26"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -7987,7 +7952,7 @@ class C "Delete [()]@25"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -8014,7 +7979,7 @@ void goo(int a) { }]@18", "Delete [int a]@43"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.goo"), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -8130,7 +8095,7 @@ static void Main(string[] args) "Insert [int a]@44"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.goo")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.goo"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -8292,13 +8257,13 @@ class C "; // TODO: The method does not need to be updated since there are no sequence points generated for it. EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.puts")), - }) + ]) ]); } @@ -8335,13 +8300,13 @@ class C } "; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.puts")), - }) + ]) ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -8399,11 +8364,10 @@ static void Main(string[] args) "Insert [string[] args]@35"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Main"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Main")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8431,11 +8395,10 @@ void M(int a, int b, int c) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8467,11 +8430,10 @@ partial void M(int a, int/*2*/b, int c) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M").PartialImplementationPart, deletedSymbolContainerProvider: c => c.GetMember("C"), partialType: "C"), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M").PartialImplementationPart, partialType: "C") - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8507,11 +8469,10 @@ static void Main(int x) "Update [bool x]@35 -> [int x]@35"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("C.Main").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Boolean))?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("C.Main").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Int32))?.ISymbol) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8544,11 +8505,10 @@ static void Main(int someInt) "Update [bool someBool]@35 -> [int someInt]@35"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("C.Main").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Boolean))?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("C.Main").FirstOrDefault(m => m.GetParameterTypes().Any(t => t.SpecialType == SpecialType.System_Int32))?.ISymbol) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -8577,11 +8537,10 @@ static void Main() "Delete [string[] args]@35"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Main"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Main")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8609,11 +8568,10 @@ void M(int a) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8652,10 +8610,9 @@ static void Main(string[] b) capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -8685,10 +8642,9 @@ static void Main(string[] b) capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Main")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -8724,11 +8680,10 @@ static void EntryPoint(string[] args) edits.VerifyEdits(expectedEdit); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Main"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.EntryPoint")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -8770,11 +8725,10 @@ static void G() EditAndContinueCapabilities.GenericAddMethodToExistingType); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.G")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.GenericAddMethodToExistingType | @@ -8817,11 +8771,10 @@ static void G() EditAndContinueCapabilities.GenericAddMethodToExistingType); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.G")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.GenericAddMethodToExistingType | @@ -8888,10 +8841,9 @@ public async Task F() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -9128,7 +9080,7 @@ static void Main(string[] args) edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Test.Main")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Test.Main"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -9165,7 +9117,7 @@ void M() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -9204,7 +9156,7 @@ void M() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"))]); edits.VerifySemanticDiagnostics(); } @@ -9833,11 +9785,10 @@ public void Method_ReadOnlyRef_Parameter_InsertParameter() "Insert [in int b]@16"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -9857,11 +9808,10 @@ public void Method_ReadOnlyRef_Parameter_Update() "Update [int b]@16 -> [in int b]@16"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -9893,11 +9843,10 @@ public void Method_ReadOnlyRef_ReturnType_Update() "Update [int M() => throw null;]@13 -> [ref readonly int M() => throw null;]@13"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("Test.M"), deletedSymbolContainerProvider: c => c.GetMember("Test")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("Test.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -9979,7 +9928,7 @@ public void Method_Partial_DeleteInsert_DefinitionPart() var srcC2 = "partial class C { partial void F(); }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), DocumentResults(), @@ -10000,12 +9949,12 @@ public void Method_Partial_DeleteInsert_ImplementationPart() var srcC2 = "partial class C { partial void F() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2)], [ DocumentResults(), DocumentResults(), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart, partialType: "C") }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart, partialType: "C")]), ]); } @@ -10019,12 +9968,12 @@ public void Method_Partial_Swap_ImplementationAndDefinitionParts() var srcB2 = "partial class C { partial void F(); }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart, partialType: "C") }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart, partialType: "C")]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart, partialType: "C") }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart, partialType: "C")]), ]); } @@ -10038,15 +9987,15 @@ public void Method_Partial_DeleteImplementation() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C"), partialType: "C") - }), + ]), ]); } @@ -10060,7 +10009,7 @@ public void Method_Partial_DeleteBoth() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( semanticEdits: [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F").PartialImplementationPart, deletedSymbolContainerProvider: c => c.GetMember("C"), partialType: "C")]), @@ -10083,14 +10032,14 @@ public void Method_Partial_DeleteInsertBoth() var srcD2 = "partial class C { partial void F() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2)], [ DocumentResults(), DocumentResults(), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").PartialImplementationPart, partialType: "C") }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").PartialImplementationPart, partialType: "C")]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").PartialImplementationPart, partialType: "C") }) + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").PartialImplementationPart, partialType: "C")]) ]); } @@ -10104,7 +10053,7 @@ public void Method_Partial_Insert() var srcB2 = "partial class C { partial void F() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( @@ -10123,12 +10072,12 @@ public void Method_Partial_Insert_Reloadable() var srcB2 = "partial class C { partial void F() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") }), + semanticEdits: [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C")]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") }), + semanticEdits: [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C")]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -10225,15 +10174,15 @@ public class A : System.Attribute {} var srcB2 = "partial class C { partial void F() { } partial void F(); }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").PartialImplementationPart, partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -10305,7 +10254,7 @@ public void Operator_Modifiers_Update_Reloadable() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -10385,11 +10334,10 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.op_Implicit"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.op_Addition"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -10413,19 +10361,19 @@ partial class C var srcB2 = srcA1; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("op_Addition")) - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("op_Implicit")) - }), + ]), ]); } @@ -10461,11 +10409,11 @@ public static implicit operator bool (C c) }"; var edits = GetTopEdits(src1, src2); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.op_Implicit")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.op_Addition")), - }); + ]); } [Fact] @@ -10486,11 +10434,11 @@ class C }"; var edits = GetTopEdits(src1, src2); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.op_Implicit")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.op_Addition")), - }); + ]); } [Fact] @@ -10503,10 +10451,10 @@ public void OperatorWithExpressionBody_ToBlockBody() edits.VerifyEdits("Update [public static C operator +(C c, C d) => d;]@10 -> [public static C operator +(C c, C d) { return c; }]@10"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.op_Addition")) - }); + ]); } [Fact] @@ -10519,10 +10467,10 @@ public void OperatorWithBlockBody_ToExpressionBody() edits.VerifyEdits("Update [public static C operator +(C c, C d) { return c; }]@10 -> [public static C operator +(C c, C d) => d;]@10"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.op_Addition")) - }); + ]); } [Fact] @@ -10541,11 +10489,11 @@ class C }"; var edits = GetTopEdits(src1, src2); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.op_Addition"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.op_Subtraction")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -10623,7 +10571,7 @@ public void Operator_Delete() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.op_LogicalNot"), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.op_LogicalNot"), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -10641,10 +10589,9 @@ public void Constructor_Parameter_AddAttribute() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -10658,10 +10605,9 @@ public void Constructor_Parameter_AddAttribute_Primary() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -10735,15 +10681,13 @@ public void Constructor_Parameter_AddAttribute_Record_NonParamTargets(string tar edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P")), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68458")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68458")] public void Constructor_Parameter_AddAttribute_Record_ReplacingSynthesizedWithCustomProperty() { var src1 = "record C(int P) { }" + s_attributeSource; @@ -10754,8 +10698,7 @@ public void Constructor_Parameter_AddAttribute_Record_ReplacingSynthesizedWithCu // We update more members than strictly necessary to avoid more complex analysis. edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -10764,7 +10707,7 @@ public void Constructor_Parameter_AddAttribute_Record_ReplacingSynthesizedWithCu SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), // TOOD: Should include update of P: https://github.com/dotnet/roslyn/issues/68458 - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -10778,13 +10721,12 @@ public void Constructor_Parameter_AddAttribute_Record_ReplacingCustomPropertyWit edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -10802,11 +10744,10 @@ public void Constructor_Parameter_Update_TypeOrRefKind_RuntimeTypeChanged( var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single()) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -10824,11 +10765,10 @@ public void Constructor_Parameter_Update_Type_Primary() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -10846,19 +10786,19 @@ public void Constructor_Parameter_Update_Type_Primary_PartialMove() var srcB2 = "partial class C(int a);"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -10871,8 +10811,7 @@ public void Constructor_Parameter_Update_Type_Record() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.x"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_x"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_x"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -10887,7 +10826,7 @@ public void Constructor_Parameter_Update_Type_Record() SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -10933,11 +10872,10 @@ public void Constructor_Parameter_Delete() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single()), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -10950,11 +10888,10 @@ public void Constructor_Parameter_Delete_Primary() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -10969,8 +10906,8 @@ public void Constructor_Parameter_Delete_Primary_Record() // The properties are updated to throw and the backing field remains in the type. // The deleted field will remain unused since adding the property back is a rude edit. edits.VerifySemantics( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -10982,7 +10919,7 @@ public void Constructor_Parameter_Delete_Primary_Record() SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11005,8 +10942,8 @@ record C(int X); // The properties are updated to throw and the backing field remains in the type. // The deleted field will remain unused since adding the property back is a rude edit. edits.VerifySemantics( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11018,7 +10955,7 @@ record C(int X); SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11033,8 +10970,8 @@ public void Constructor_Parameter_Delete_Primary_Record_Struct() // The properties are updated to throw and the backing field remains in the type. // The deleted field will remain unused since adding the property back is a rude edit. edits.VerifySemantics( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11045,7 +10982,7 @@ public void Constructor_Parameter_Delete_Primary_Record_Struct() SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11058,8 +10995,7 @@ public void Constructor_Parameter_Delete_Primary_Record_ReplacingSynthesizedWith var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -11071,7 +11007,7 @@ public void Constructor_Parameter_Delete_Primary_Record_ReplacingSynthesizedWith SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11084,8 +11020,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomProperty_WithU var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), @@ -11095,7 +11030,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomProperty_WithU SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -11109,8 +11044,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomProperty_WithA var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Y"), syntaxMap: syntaxMap[0]), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), @@ -11120,7 +11054,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomProperty_WithA SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11133,8 +11067,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomField_WithUpda var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), @@ -11144,7 +11077,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomField_WithUpda SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -11157,8 +11090,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomPropertyDelete var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), @@ -11170,7 +11102,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomPropertyDelete SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11183,8 +11115,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11195,7 +11126,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11208,8 +11139,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("C.Deconstruct").Single(m => m.Parameters is [_])), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11221,7 +11151,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11234,8 +11164,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11247,7 +11176,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11260,8 +11189,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Y"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11273,7 +11201,7 @@ public void Constructor_Parameter_Delete_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11299,11 +11227,11 @@ class C(int x) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11346,11 +11274,10 @@ public void Constructor_Parameter_Insert() "Insert [int b]@26"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single()) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -11372,11 +11299,10 @@ public void Constructor_Parameter_Insert_Primary_Uncaptured(string keyword) "Insert [int b]@16"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -11384,8 +11310,7 @@ public void Constructor_Parameter_Insert_Primary_Uncaptured(string keyword) capabilities: EditAndContinueCapabilities.Baseline); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69159")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69159")] public void Constructor_Parameter_Insert_Primary_Captured_Class() { var src1 = "class C(int a) { int X => a; }"; @@ -11393,12 +11318,11 @@ public void Constructor_Parameter_Insert_Primary_Captured_Class() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_X")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); // TODO: should report rude edit https://github.com/dotnet/roslyn/issues/69159 @@ -11430,8 +11354,7 @@ public void Constructor_Parameter_Insert_Primary_Record() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11443,7 +11366,7 @@ public void Constructor_Parameter_Insert_Primary_Record() SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.U")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11501,11 +11424,10 @@ public void Constructor_Parameter_Insert_In() "Insert [in int b]@12"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetParameterlessConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single()) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -11522,8 +11444,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), @@ -11532,7 +11453,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11545,8 +11466,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), @@ -11555,7 +11475,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11568,8 +11488,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("C.Deconstruct").Single(m => m.Parameters is [_, _])), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11579,7 +11498,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11592,8 +11511,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -11603,7 +11521,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11616,8 +11534,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Y")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), @@ -11627,7 +11544,7 @@ public void Constructor_Parameter_Insert_Primary_Record_WithCustomDeconstructor_ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -11687,11 +11604,11 @@ class C(int x, int y) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -11775,8 +11692,7 @@ public void Constructor_Parameter_Reorder_Primary_NotLifted(string keyword) capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68708")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")] public void Constructor_Parameter_Reorder_Primary_NotLifted_Record_Struct() { var src1 = "record struct C(int x, byte y) { }"; @@ -11788,8 +11704,7 @@ public void Constructor_Parameter_Reorder_Primary_NotLifted_Record_Struct() capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68708")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")] public void Constructor_Parameter_Reorder_Primary_Lifted_Struct() { var src1 = "struct C(int x, byte y) { int M() => x + y; }"; @@ -11801,8 +11716,7 @@ public void Constructor_Parameter_Reorder_Primary_Lifted_Struct() capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68708")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")] public void Constructor_Parameter_Reorder_Primary_Lifted_Class() { var src1 = "class C(int x, byte y) { int M() => x + y; }"; @@ -11817,8 +11731,7 @@ public void Constructor_Parameter_Reorder_Primary_Lifted_Class() capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68708")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68708")] [WorkItem("https://github.com/dotnet/roslyn/issues/69894")] public void Constructor_Parameter_Reorder_Primary_Lifted_Record() { @@ -11995,14 +11908,14 @@ public void Constructor_Parameter_DeleteInsert_Primary(string keywords) var srcB2 = keywords + " C(int P);"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -12019,16 +11932,16 @@ public void Constructor_Parameter_DeleteInsert_Primary_Record(string keywords) var srcB2 = keywords + " C(int P);"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -12044,15 +11957,15 @@ public void Constructor_Parameter_DeleteInsert_ReplacingPrimaryWithNonPrimary(st var srcB2 = "partial " + keyword + " C { public C(int a) { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "a"}]), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -12066,13 +11979,13 @@ public void Constructor_Parameter_DeleteInsert_ReplacingPrimaryWithNonPrimary_Re var srcB2 = "partial record C { public int P { get; init; } public C(int P) { } public void Deconstruct(out int P) { P = this.P; } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -12081,7 +11994,7 @@ public void Constructor_Parameter_DeleteInsert_ReplacingPrimaryWithNonPrimary_Re SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "P"}]), partialType: "C", preserveLocalVariables: true), - }), + ]), ]); } @@ -12124,13 +12037,13 @@ public void Constructor_Parameter_DeleteInsert_ReplacingNonPrimaryWithPrimary_Wi var srcB2 = "partial record C(int P) { public int P { get; init; } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "P" }]), partialType: "C", preserveLocalVariables: true), @@ -12139,7 +12052,7 @@ public void Constructor_Parameter_DeleteInsert_ReplacingNonPrimaryWithPrimary_Wi SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), - }), + ]), ]); } @@ -12153,18 +12066,18 @@ public void Constructor_Parameter_DeleteInsert_ReplacingNonPrimaryWithPrimary_Wi var srcB2 = "partial record C(int P) { public int P; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), @@ -12172,7 +12085,7 @@ public void Constructor_Parameter_DeleteInsert_ReplacingNonPrimaryWithPrimary_Wi SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.Parameters is [{ Name: "P" }]), partialType: "C", preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Deconstruct")), - }), + ]), ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -12187,27 +12100,27 @@ public void Constructor_Parameter_DeleteInsert_SwappingNonPrimaryWithPrimary_Rec var srcB2 = "partial record C() { public C(int P) : this() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - } + ] ), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.Parameters is [{ Name: "P" }])), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.Parameters is []), partialType: "C", preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), - }), + ]), ]); } @@ -12221,26 +12134,26 @@ public void Constructor_Parameter_DeleteInsert_ReplacingPropertyWithField_Record var srcB2 = "partial record C(int P) { public int P; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), partialType: "C", preserveLocalVariables: true), - }), + ]), ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -12306,10 +12219,9 @@ public C(int a) : base(a + 1) { } capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.GenericUpdateMethod); } @@ -12364,10 +12276,9 @@ public C(int a) { } capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.GenericUpdateMethod); } @@ -12426,8 +12337,7 @@ public void Constructor_Instance_Update_Initializer_Insert_Primary(string keywor SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Constructor_Instance_Update_Initializer_StackAlloc_Update() { var src1 = "class C { C() : this(stackalloc int[1]) {} C(Span span) {} }"; @@ -12438,8 +12348,7 @@ public void Constructor_Instance_Update_Initializer_StackAlloc_Update() Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc int[2]", FeaturesResources.constructor)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Constructor_Instance_Update_Initializer_StackAlloc_Delete() { var src1 = "class C { C() : this(stackalloc int[1]) {} C(Span span) {} }"; @@ -12450,8 +12359,7 @@ public void Constructor_Instance_Update_Initializer_StackAlloc_Delete() Diagnostic(RudeEditKind.StackAllocUpdate, "C()", FeaturesResources.constructor)); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void Constructor_Instance_Update_Initializer_StackAlloc_Insert() { var src1 = "class C { C() : this(default) {} C(Span span) {} }"; @@ -12516,10 +12424,9 @@ public class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -12547,10 +12454,9 @@ public class C : B edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -12578,10 +12484,9 @@ public class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -12609,10 +12514,9 @@ public class C : B edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -12652,8 +12556,7 @@ partial void C(int x) SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("C").PartialImplementationPart, partialType: "C")); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/2068")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2068")] public void Constructor_Instance_Update_Modifier_Extern_Add() { var src1 = "class C { }"; @@ -12679,10 +12582,9 @@ public void Constructor_Instance_Insert_Struct(string keyword) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "X" }])) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -12695,10 +12597,9 @@ public void Constructor_Instance_Insert_Struct_Primary() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "X" }])) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -12728,11 +12629,10 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class(string keyword) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "X"}])), SemanticEdit(SemanticEditKind.Delete, c => c.GetParameterlessConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -12745,11 +12645,10 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class_Primary() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetParameterlessConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -12762,8 +12661,7 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class_Primary_Record() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), @@ -12772,7 +12670,7 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class_Primary_Record() SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetParameterlessConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -12785,8 +12683,7 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class_Primary_Record_Ge var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryConstructor("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetPrimaryDeconstructor("C")), @@ -12795,7 +12692,7 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class_Primary_Record_Ge SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.GetHashCode")), SemanticEdit(SemanticEditKind.Update, c => c.GetCopyConstructor("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetParameterlessConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType | @@ -12838,10 +12735,9 @@ public void Constructor_Instance_Insert_ReplacingDefault_Class_WithMemberInitial edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -12877,7 +12773,7 @@ public void Constructor_Instance_Insert_ReplacingDefault_WithStackAllocInMemberI var srcB2 = "partial class C { static int G(System.Span span) => 1; public C() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), @@ -12928,7 +12824,7 @@ public void Constructor_Instance_Insert_ReplacingExplicitWithDefault_WithStackAl var srcB2 = "partial class C { static int G(System.Span span) => 1; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), @@ -12956,7 +12852,7 @@ public void Constructor_Instance_Insert_UpdatingImplicit( edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -12976,13 +12872,13 @@ public void Constructor_Instance_Insert_UpdatingImplicit_Partial( var srcB2 = "partial " + keyword + " C { " + accessibility + " C() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // no change in document A DocumentResults(), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true)]), ]); } @@ -12999,7 +12895,7 @@ public void Constructor_Instance_Insert_AddingParameterless( edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetParameterlessConstructor("C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetParameterlessConstructor("C"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13016,7 +12912,7 @@ public void Constructor_Instance_Insert_AddingParameterless_Primary( edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetParameterlessConstructor("C")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetParameterlessConstructor("C"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13033,13 +12929,13 @@ public void Constructor_Instance_Insert_AddingParameterless_Partial( var srcB2 = "partial " + keyword + " C { public C(int a) { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetParameterlessConstructor("C"), partialType: "C") - }), + ]), // no change in document B DocumentResults(), @@ -13060,13 +12956,13 @@ public void Constructor_Instance_Insert_AddingParameterless_Partial_Primary( var srcB2 = "partial " + keyword + " C(int a) { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetParameterlessConstructor("C")) - }), + ]), // no change in document B DocumentResults(), @@ -13151,10 +13047,9 @@ public void Constructor_Instance_Delete_Struct(string keyword) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "X" }]), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13167,10 +13062,9 @@ public void Constructor_Instance_Delete_Struct_Primary() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "X" }]), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13183,8 +13077,7 @@ public void Constructor_Instance_Delete_Struct_Primary_Record() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), @@ -13193,7 +13086,7 @@ public void Constructor_Instance_Delete_Struct_Primary_Record() SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13208,11 +13101,10 @@ public void Constructor_Instance_Delete_ReplacingWithDefault_Class(string keywor var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ // The compiler emits default constructor automatically SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "X"}]), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13225,11 +13117,10 @@ public void Constructor_Instance_Delete_ReplacingWithDefault_Class_Primary() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ // The compiler emits default constructor automatically SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13242,8 +13133,7 @@ public void Constructor_Instance_Delete_ReplacingWithDefault_Class_Primary_Recor var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ // The compiler emits default constructor automatically SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), @@ -13254,7 +13144,7 @@ public void Constructor_Instance_Delete_ReplacingWithDefault_Class_Primary_Recor SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -13287,7 +13177,7 @@ public void Constructor_Instance_Delete_UpdatingImplicit( edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -13318,10 +13208,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) - }); + ]); } [Theory] @@ -13334,7 +13223,7 @@ public void Constructor_Instance_Delete_WithParameters([CombinatorialValues("rec var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "x" }]), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "x" }]), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -13348,7 +13237,7 @@ public void Constructor_Instance_Delete_Primary_WithParameters([CombinatorialVal var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "b" }]), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [{ Name: "b" }]), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -13361,7 +13250,7 @@ public void Constructor_Instance_Delete_Primary_Class() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.FirstOrDefault(c => c.Parameters.Length == 1), deletedSymbolContainerProvider: c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C").InstanceConstructors.FirstOrDefault(c => c.Parameters.Length == 1), deletedSymbolContainerProvider: c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.Baseline); } @@ -13374,8 +13263,7 @@ public void Constructor_Instance_Delete_Primary_Record() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetPrimaryDeconstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.PrintMembers")), SemanticEdit(SemanticEditKind.Update, c => c.GetSpecializedEqualsOverload("C")), @@ -13385,7 +13273,7 @@ public void Constructor_Instance_Delete_Primary_Record() SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -13410,13 +13298,13 @@ public void Constructor_Instance_Delete_Public_PartialWithInitializerUpdate() var srcB2 = "partial class C { int x = 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true)]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) }) + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true)]) ]); } @@ -13616,16 +13504,16 @@ public void Constructor_Instance_Partial_DeletePrivateInsertPrivate() var srcB2 = "partial class C { C() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -13639,16 +13527,16 @@ public void Constructor_Instance_Partial_DeletePublicInsertPublic() var srcB2 = "partial class C { public C() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -13662,7 +13550,7 @@ public void Constructor_Instance_Partial_DeletePrivateInsertPublic() var srcB2 = "partial class C { public C() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // delete of the constructor in partial part will be reported as rude edit in the other document where it was inserted back with changed accessibility DocumentResults( @@ -13683,13 +13571,13 @@ public void Constructor_Instance_Partial_InsertPublicDeletePublic() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), @@ -13706,13 +13594,13 @@ public void Constructor_Instance_Partial_InsertPrivateDeletePrivate() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), @@ -13729,13 +13617,13 @@ public void Constructor_Instance_Partial_DeleteInternalInsertInternal() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), @@ -13752,13 +13640,13 @@ public void Constructor_Instance_Partial_InsertInternalDeleteInternal_WithBody() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), @@ -13775,7 +13663,7 @@ public void Constructor_Instance_Partial_InsertPublicDeletePrivate() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: [Diagnostic(RudeEditKind.ChangingAccessibility, "public C()", FeaturesResources.constructor)]), @@ -13795,7 +13683,7 @@ public void Constructor_Instance_Partial_InsertInternalDeletePrivate() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: [Diagnostic(RudeEditKind.ChangingAccessibility, "internal C()", FeaturesResources.constructor)]), @@ -13852,7 +13740,7 @@ partial class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -13897,7 +13785,7 @@ partial class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -13956,7 +13844,7 @@ public C() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -14002,7 +13890,7 @@ partial class C var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])], capabilities: EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition); edits.VerifySemanticDiagnostics( @@ -14106,19 +13994,19 @@ partial class C var syntaxMapB = GetSyntaxMap(srcB1, srcB2)[0]; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // No changes in document A DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Int32"), partialType: "C", syntaxMap: syntaxMapB), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Boolean"), partialType: "C", syntaxMap: syntaxMapB), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "UInt32"), partialType: "C", syntaxMap: syntaxMapB), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Byte"), partialType: "C", syntaxMap: null), - }) + ]) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -14165,7 +14053,7 @@ partial class C "; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // No changes in document A DocumentResults(), @@ -14186,18 +14074,18 @@ public void Constructor_Instance_Partial_Implicit_Update() var srcB2 = "partial class C { int G = 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -14211,17 +14099,17 @@ public void PartialDeclaration_Delete() var srcB2 = "partial class C { int x = 2; void F() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true)]), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -14235,17 +14123,17 @@ public void PartialDeclaration_Insert() var srcB2 = "partial class C { int x = 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true)]), ]); } @@ -14259,24 +14147,23 @@ public void PartialDeclaration_Insert_Reloadable() var srcB2 = ReloadableAttributeSrc + "[CreateNewOnMetadataUpdate]partial class C { int x = 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), + ]), - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/2068")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2068")] public void Constructor_Static_Update_Modifier_Extern_Add() { var src1 = "class C { }"; @@ -14310,7 +14197,7 @@ public void Constructor_Static_Delete_Reloadable() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C")) }, + [SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -14323,7 +14210,7 @@ public void Constructor_Static_Insert() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").StaticConstructors.Single()) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").StaticConstructors.Single())], EditAndContinueCapabilities.AddMethodToExistingType); } @@ -14337,16 +14224,16 @@ public void Constructor_Static_Partial_DeleteInsert() var srcB2 = "partial class C { static C() { } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -14360,13 +14247,13 @@ public void Constructor_Static_Partial_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), partialType: "C", preserveLocalVariables: true) - }), + ]), // delete of the constructor in partial part will be represented as a semantic update in the other document where it was inserted back DocumentResults(), @@ -14432,10 +14319,9 @@ public class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Finalize"), preserveLocalVariables: false) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -14459,10 +14345,9 @@ public class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.Finalize"), preserveLocalVariables: false) - }); + ]); } #endregion @@ -14482,7 +14367,7 @@ public void MemberInitializer_Update_Field() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14495,7 +14380,7 @@ public void MemberInitializer_Update_Field_Event() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14511,7 +14396,7 @@ public void MemberInitializer_Update_Property() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14538,14 +14423,14 @@ public void MemberInitializer_Update_Remove_Partial_Field() var srcB2 = "partial class C { int F ; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ]); } @@ -14559,15 +14444,15 @@ public void MemberInitializer_Update_Remove_Partial_Property() var srcB2 = "partial class C { int F { get; } }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_F")) - }), + ]), ]); } @@ -14641,14 +14526,14 @@ public void MemberInitializer_PropertyInsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.a").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), partialType: "C", preserveLocalVariables: true) - }), + ]), DocumentResults(), ]); } @@ -14666,7 +14551,7 @@ public void MemberInitializer_Field_Update3() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14683,11 +14568,10 @@ public void MemberInitializer_PropertyUpdate3() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.a").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -14729,13 +14613,12 @@ public void MemberInitializer_PropertyDelete(string ctor) edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.a"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_a"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_a"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -14753,7 +14636,7 @@ public void MemberInitializer_Update_Field_StaticCtorUpdate1() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)]); } [Fact] @@ -14766,7 +14649,7 @@ public void MemberInitializer_Update_Property_StaticCtorUpdate1() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)]); } [Fact] @@ -14807,7 +14690,7 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate_Public() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14820,7 +14703,7 @@ public void MemberInitializer_Update_Property_InstanceCtorUpdate_Public() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14836,7 +14719,7 @@ public void MemberInitializer_Update_Field_StaticCtorUpdate2() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)]); } [Fact] @@ -14849,7 +14732,7 @@ public void MemberInitializer_Update_Property_StaticCtorUpdate2() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)]); } [Theory] @@ -14867,7 +14750,7 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate2(string typeKind) edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Theory] @@ -14883,7 +14766,7 @@ public void MemberInitializer_Update_Property_InstanceCtorUpdate2(string typeKin edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14899,7 +14782,7 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate3() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14912,7 +14795,7 @@ public void MemberInitializer_Update_Property_InstanceCtorUpdate3() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14928,7 +14811,7 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate4() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -14944,11 +14827,10 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate_Class() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(int)"), preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(string)"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -14964,11 +14846,10 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate_Struct() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(int)"), preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(bool)"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -14981,11 +14862,10 @@ public void MemberInitializer_Update_Property_InstanceCtorUpdate5() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(int)"), preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(bool)"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -14998,11 +14878,10 @@ public void MemberInitializer_Update_Property_Struct_InstanceCtorUpdate5() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(int)"), preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(bool)"), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -15018,10 +14897,9 @@ public void MemberInitializer_Update_Field_InstanceCtorUpdate6() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(m => m.ToString() == "C.C(bool)"), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -15037,7 +14915,7 @@ public void MemberInitializer_Update_Field_StaticCtorInsertImplicit() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").StaticConstructors.Single()) }); + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").StaticConstructors.Single())]); } [Fact] @@ -15054,7 +14932,7 @@ public void MemberInitializer_Update_Field_StaticCtorInsertExplicit() "Update [a]@21 -> [a = 0]@21"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").StaticConstructors.Single()) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").StaticConstructors.Single())], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -15071,7 +14949,7 @@ public void MemberInitializer_Update_Field_Constructor_Instance_InsertExplicit(s edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Theory] @@ -15087,7 +14965,7 @@ public void MemberInitializer_Update_Property_Constructor_Instance_InsertExplici edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true)]); } [Fact] @@ -15108,10 +14986,9 @@ public void MemberInitializer_Update_Field_GenericType() capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.GenericUpdateMethod); } @@ -15128,10 +15005,9 @@ public void MemberInitializer_Update_Property_GenericType() capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); } @@ -15162,8 +15038,7 @@ public void MemberInitializer_Update_StackAllocInConstructor_ThisInitializer() edits.VerifySemanticDiagnostics(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/68731")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68731")] public void MemberInitializer_Update_StackAllocInConstructor_Initializer_Field() { var src1 = "class C : B { int a = 1; C() : base(stackalloc int[1]) { } } class B(System.Span s);"; @@ -15187,8 +15062,7 @@ public void FieldInitializerUpdate_StackAllocInConstructor_PrimaryBaseInitialize edits.VerifySemanticDiagnostics(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/67307")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67307")] public void MemberInitializer_Update_StackAllocInOtherInitializer() { var src1 = "class C { int a = 1; int b = G(stackalloc int[10]); static int G(Span span) => 1; }"; @@ -15470,10 +15344,9 @@ public void MemberInitializer_Update_PartialTypeWithSingleDeclaration_Field() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -15486,10 +15359,9 @@ public void MemberInitializer_Update_PartialTypeWithSingleDeclaration_Property() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -15505,10 +15377,9 @@ public void MemberInitializer_Update_PartialTypeWithMultipleDeclarations_Field() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true) - }); + ]); } [Fact] @@ -15521,10 +15392,9 @@ public void MemberInitializer_Update_PartialTypeWithMultipleDeclarations_Propert edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true) - }); + ]); } [Theory] @@ -15608,7 +15478,7 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -15641,7 +15511,7 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -15678,7 +15548,7 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -15715,7 +15585,7 @@ public C() {} edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0])]); } [Fact] @@ -15754,11 +15624,10 @@ public C(bool b) {} edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[0], syntaxMap[0]), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[1], syntaxMap[0]) - }); + ]); } [Fact] @@ -15797,11 +15666,10 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[0], syntaxMap[0]), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[1], syntaxMap[0]) - }); + ]); } [Fact] @@ -15840,11 +15708,10 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[0], syntaxMap[0]), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[1], syntaxMap[0]) - }); + ]); } [Fact] @@ -15883,10 +15750,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Int32 a)"), syntaxMap[0]) - }); + ]); } [Fact] @@ -15925,10 +15791,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Int32 a)"), syntaxMap[0]) - }); + ]); } [Fact] @@ -15967,10 +15832,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Boolean b)"), syntaxMap[0]) - }); + ]); } [Fact] @@ -16009,10 +15873,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Boolean b)")) - }); + ]); } [Fact] @@ -16051,10 +15914,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Boolean b)"), syntaxMap[0]) - }); + ]); } [Fact] @@ -16092,10 +15954,9 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Boolean b)")) - }); + ]); } [Fact] @@ -16150,10 +16011,9 @@ public C(bool b) edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(ctor => ctor.ToTestDisplayString() == "C..ctor(System.Boolean b)"), syntaxMap[0]) - }); + ]); } [Theory] @@ -16190,10 +16050,9 @@ class C : B edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) - }); + ]); } [Theory] @@ -16231,10 +16090,9 @@ class C : B edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) - }); + ]); } [Fact] @@ -16277,11 +16135,10 @@ partial class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), syntaxMap[0]), - }); + ]); } [Theory] @@ -16295,10 +16152,9 @@ public void FieldInitializerUpdate_Lambdas_InsertPrimaryConstructorParameterUse( var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters is [_, _]), preserveLocalVariables: true), - }); + ]); } [Fact] @@ -16334,11 +16190,10 @@ class C edits.VerifySemantics( activeStatements, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[0], syntaxMap[0]), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors[1], syntaxMap[0]), - }); + ]); } [Fact] @@ -16405,16 +16260,16 @@ public void MemberInitializer_Update_Reloadable_Partial() var srcB2 = "partial class C { int y = 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -16490,7 +16345,7 @@ public void Field_Modifier_Add_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -16512,13 +16367,13 @@ public void Field_Attribute_Add_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }), + ]), DocumentResults(), ], @@ -16602,11 +16457,10 @@ public void Field_Insert() "Insert [a = 1]@14"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.a")), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -16671,12 +16525,11 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.b")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.c")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.d")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType); } @@ -16790,11 +16643,10 @@ public C() var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.B")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -16831,11 +16683,10 @@ class C var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.B")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType | @@ -16975,12 +16826,11 @@ class C var syntaxMap = GetSyntaxMap(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.B")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").Constructors.Single()), SemanticEdit(SemanticEditKind.Delete, c => c.GetParameterlessConstructor("C"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.AddMethodToExistingType); } @@ -17055,11 +16905,10 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.a")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.b")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -17081,11 +16930,10 @@ class C edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.a")), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -17099,15 +16947,15 @@ public void Field_Attribute_DeleteInsertUpdate_WithInitializer() var srcB2 = "partial class C { [System.Obsolete]int a = 2; }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.a")), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -17255,13 +17103,12 @@ public void Property_ExpressionBody_Rename() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Q")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -17277,10 +17124,10 @@ public void Property_ExpressionBody_Update() "Update [int P => 1;]@10 -> [int P => 2;]@10", "Update [=> 1]@16 -> [=> 2]@16"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48628")] @@ -17310,10 +17157,10 @@ public void Property_ExpressionBodyToBlockBody1() "Insert [get { return 2; }]@18", "Delete [=> 1]@16"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -17332,11 +17179,10 @@ public void Property_ExpressionBodyToBlockBody2() "Delete [=> 1]@16"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_P"), preserveLocalVariables: false) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -17354,10 +17200,10 @@ public void Property_BlockBodyToExpressionBody1() "Delete [{ get { return 2; } }]@16", "Delete [get { return 2; }]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -17376,11 +17222,10 @@ public void Property_BlockBodyToExpressionBody2() "Delete [set { }]@36"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17397,10 +17242,10 @@ public void Property_ExpressionBodyToGetterExpressionBody() "Insert [get => 2;]@18", "Delete [=> 1]@16"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17416,10 +17261,10 @@ public void Property_GetterExpressionBodyToExpressionBody() "Delete [{ get => 2; }]@16", "Delete [get => 2;]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17432,10 +17277,10 @@ public void Property_GetterBlockBodyToGetterExpressionBody() edits.VerifyEdits("Update [get { return 2; }]@18 -> [get => 2;]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17448,10 +17293,10 @@ public void Property_SetterBlockBodyToSetterExpressionBody() edits.VerifyEdits("Update [set { }]@18 -> [set => F();]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17464,10 +17309,10 @@ public void Property_InitBlockBodyToInitExpressionBody() edits.VerifyEdits("Update [init { }]@18 -> [init => F();]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod, preserveLocalVariables: false), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17480,10 +17325,10 @@ public void Property_GetterExpressionBodyToGetterBlockBody() edits.VerifyEdits("Update [get => 2;]@18 -> [get { return 2; }]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17496,10 +17341,10 @@ public void Property_GetterBlockBodyWithSetterToGetterExpressionBodyWithSetter() edits.VerifyEdits("Update [get => 2;]@18 -> [get { return 2; }]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -17512,11 +17357,11 @@ public void Property_GetterExpressionBodyWithSetterToGetterBlockBodyWithSetter() edits.VerifyEdits("Update [get { return 2; }]@18 -> [get => 2;]@18"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P"), preserveLocalVariables: false), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -17528,13 +17373,12 @@ public void Property_Rename1() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Q")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -17574,15 +17418,14 @@ public void Property_Rename3() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Q")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -17595,15 +17438,14 @@ public void Property_Rename4() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Q")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -17632,13 +17474,12 @@ public void Property_RenameAndUpdate() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Q")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.Q")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -17669,12 +17510,11 @@ public void Property_Delete(string keyword) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17687,11 +17527,10 @@ public void Property_Delete_GetOnly() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17704,12 +17543,11 @@ public void Property_Delete_Auto_Class() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17725,12 +17563,11 @@ public void Property_Delete_Auto_Struct() // The properties are updated to throw and the backing field remains in the type. // The deleted field will remain unused since adding the property/event back is a rude edit. edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17743,10 +17580,9 @@ public void PropertyAccessorDelete1() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17759,10 +17595,9 @@ public void PropertyAccessorDelete2() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -17849,15 +17684,14 @@ public void Property_Update_Type() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_P")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -17893,15 +17727,14 @@ public void Property_Update_Type_WithBodies() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_P")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.P")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -17931,12 +17764,11 @@ public void Property_Update_AddAttribute() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -17954,7 +17786,7 @@ public void Property_Update_AddAttribute_FieldTarget() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -17971,11 +17803,10 @@ public void PropertyAccessorUpdate_AddAttribute() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_P")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -17992,7 +17823,7 @@ public void PropertyAccessorUpdate_AddAttribute2() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod)], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -18009,7 +17840,7 @@ public void Property_Insert() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -18022,7 +17853,7 @@ public void Property_Insert_Static() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -18173,7 +18004,7 @@ public void Property_Insert_Auto() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -18186,7 +18017,7 @@ public void Property_Insert_Auto_Static() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType); } @@ -18199,7 +18030,7 @@ public void Property_Insert_Auto_GenericType() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType | @@ -18220,7 +18051,7 @@ public void Property_Insert_Auto_GenericType_Static() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("P"))], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType | @@ -18259,10 +18090,9 @@ public void Property_Private_AccessorDelete() edits.VerifyEdits("Delete [set { _p = value; }]@44"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -18361,11 +18191,10 @@ public void Property_Auto_Private_AccessorDelete_Get() edits.VerifyEdits("Delete [get;]@18"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_P")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -18412,11 +18241,10 @@ public void Propert_Auto_Private_AccessorDelete_Set() edits.VerifyEdits("Delete [set;]@23"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -18431,11 +18259,10 @@ public void Propert_Auto_Private_AccessorDelete_Init() edits.VerifyEdits("Delete [init;]@23"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_P"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), preserveLocalVariables: true), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -18462,10 +18289,9 @@ public void Property_Auto_Accessor_Update_ReplacingExplicitWithImplicit() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -18484,10 +18310,9 @@ public void Property_Auto_Accessor_Update_ReplacingExplicitWithImplicit_GenericT var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) - }, + ], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.GenericAddFieldToExistingType | @@ -18509,10 +18334,9 @@ public void Property_Auto_Accessor_Update_ReplacingImplicitWithExplicit() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -18525,10 +18349,9 @@ public void Property_Auto_Accessor_Update_ReplacingImplicitWithExplicit_GenericT var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) - }, + ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); edits.VerifySemanticDiagnostics( @@ -18547,10 +18370,9 @@ public void Property_Auto_Accessor_Update_ReplacingImplicitWithExpressionBodiedP var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -18563,10 +18385,9 @@ public void Property_Auto_Accessor_Update_ReplacingImplicitWithExpressionBodiedP var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.P").GetMethod) - }, + ], capabilities: EditAndContinueCapabilities.GenericUpdateMethod); edits.VerifySemanticDiagnostics( @@ -18606,13 +18427,12 @@ public void Property_ReadOnlyRef_Update() "Update [int P { get; }]@13 -> [ref readonly int P { get; }]@13"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("Test.P"), deletedSymbolContainerProvider: c => c.GetMember("Test")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("Test.get_P"), deletedSymbolContainerProvider: c => c.GetMember("Test")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("Test.P")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("Test.get_P")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -18630,14 +18450,14 @@ public void Property_Partial_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod) - }), + ]), DocumentResults(), ]); @@ -18653,14 +18473,14 @@ public void PropertyInit_Partial_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("Q").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("Q").SetMethod) - }), + ]), DocumentResults(), ]); @@ -18678,16 +18498,16 @@ public void Property_Auto_Partial_InsertDelete() // Accessors need to be updated even though they do not have an explicit body. // There is still a sequence point generated for them whose location needs to be updated. EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("Q").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("Q").SetMethod), - }), + ]), DocumentResults(), ]); } @@ -18704,15 +18524,15 @@ public void Property_AutoWithInitializer_Partial_InsertDelete() // Accessors need to be updated even though they do not have an explicit body. // There is still a sequence point generated for them whose location needs to be updated. EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), DocumentResults(), ]); @@ -18728,10 +18548,10 @@ public void Property_WithExpressionBody_Partial_InsertDeleteUpdate() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod) }), + semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod)]), DocumentResults(), ]); @@ -18809,15 +18629,14 @@ readonly struct S var edits = GetTopEdits(src1, src2); // updates only for accessors whose modifiers were explicitly updated - edits.VerifySemantics(new[] - { + edits.VerifySemantics( + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("S").GetMember("P2").GetMethod, preserveLocalVariables: false), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("S").GetMember("P3").SetMethod, preserveLocalVariables: false) - }); + ]); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69317")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69317")] public void Property_Rename_ShadowingPrimaryParameter() { var src1 = @" @@ -18842,20 +18661,18 @@ class C(int A, int B) // Update D getter/setter to use deleted B property edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.B"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_B"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_B"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.D")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_D")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_D")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69317")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69317")] [WorkItem("https://github.com/dotnet/roslyn/issues/69216")] public void Property_Rename_ShadowingPrimaryParameter_WithInitializer() { @@ -18881,8 +18698,7 @@ class C(int A, int B) // Update D getter/setter to use deleted B property edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetPrimaryConstructor("C"), preserveLocalVariables: true), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.B"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_B"), deletedSymbolContainerProvider: c => c.GetMember("C")), @@ -18890,7 +18706,7 @@ class C(int A, int B) SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.D")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_D")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_D")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); } @@ -18937,10 +18753,10 @@ public void Indexer_GetterUpdate() edits.VerifyEdits( "Update [get { return 1; }]@28 -> [get { return 2; }]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -18954,10 +18770,10 @@ public void Indexer_SetterUpdate() edits.VerifyEdits( "Update [set { System.Console.WriteLine(value); }]@46 -> [set { System.Console.WriteLine(value + 1); }]@46"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -18971,10 +18787,10 @@ public void Indexer_InitUpdate() edits.VerifyEdits( "Update [init { System.Console.WriteLine(value); }]@46 -> [init { System.Console.WriteLine(value + 1); }]@46"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: false) - }); + ]); } [Fact] @@ -18989,11 +18805,11 @@ public void IndexerWithExpressionBody_Update() "Update [int this[int a] => 1;]@10 -> [int this[int a] => 2;]@10", "Update [=> 1]@26 -> [=> 2]@26"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19010,11 +18826,11 @@ public void Indexer_ExpressionBodyToBlockBody() "Insert [get { return 1; }]@28", "Delete [=> 1]@26"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19031,11 +18847,11 @@ public void Indexer_BlockBodyToExpressionBody() "Delete [{ get { return 1; } }]@26", "Delete [get { return 1; }]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19048,10 +18864,10 @@ public void Indexer_GetterExpressionBodyToBlockBody() edits.VerifyEdits("Update [get => 1;]@28 -> [get { return 1; }]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: false) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19079,11 +18895,11 @@ public void Indexer_GetterExpressionBodyToExpressionBody() "Delete [{ get => 1; }]@26", "Delete [get => 1;]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19099,11 +18915,11 @@ public void Indexer_ExpressionBodyToGetterExpressionBody() "Insert [get => 1;]@28", "Delete [=> 1]@26"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19116,10 +18932,10 @@ public void Indexer_GetterBlockBodyToGetterExpressionBody() edits.VerifyEdits("Update [get { return 1; }]@28 -> [get => 1;]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: false), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19132,11 +18948,11 @@ public void Indexer_SetterBlockBodyToSetterExpressionBody() edits.VerifyEdits("Update [set { }]@28 -> [set => F();]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19149,11 +18965,11 @@ public void Indexer_InitBlockBodyToInitExpressionBody() edits.VerifyEdits("Update [init { }]@28 -> [init => F();]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19166,11 +18982,11 @@ public void Indexer_GetterExpressionBodyToGetterBlockBody() edits.VerifyEdits("Update [get => 1;]@28 -> [get { return 1; }]@28"); - edits.VerifySemantics(ActiveStatementsDescription.Empty, new[] - { + edits.VerifySemantics(ActiveStatementsDescription.Empty, + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item"), preserveLocalVariables: false), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item"), preserveLocalVariables: false) - }); + ]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17681")] @@ -19188,12 +19004,11 @@ public void Indexer_GetterAndSetterBlockBodiesToExpressionBody() "Delete [set { Console.WriteLine(0); }]@46"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -19213,12 +19028,11 @@ public void Indexer_ExpressionBodyToGetterAndSetterBlockBodies() "Delete [=> 1]@26"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Item")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -19381,15 +19195,14 @@ public void Indexer_Update_Type() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Item")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -19406,13 +19219,12 @@ public void Indexer_Update_Type_WithExpressionBody() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -19460,15 +19272,14 @@ public void Indexer_Parameter_Update_Type() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Item")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -19481,12 +19292,11 @@ public void Indexer_Parameter_Rename() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.set_Item")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -19507,10 +19317,9 @@ public class A : System.Attribute { public A(int x) {} } var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); edits.VerifySemanticDiagnostics( @@ -19527,15 +19336,14 @@ public void Indexer_Parameter_Insert() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Item")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -19548,15 +19356,14 @@ public void Indexer_Parameter_Delete() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.set_Item")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -19656,7 +19463,7 @@ class C edits.VerifyEdits("Insert [set { }]@67"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("this[]").SetMethod) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("this[]").SetMethod)], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -19679,12 +19486,11 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -19711,10 +19517,9 @@ public T this[int i] var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -19734,10 +19539,9 @@ class C var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.set_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -19821,13 +19625,12 @@ public void Indexer_ReadOnlyRef_ReturnType_Update() "Update [int this[int i] => throw null;]@10 -> [ref readonly int this[int i] => throw null;]@10"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.this[]"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.get_Item"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.get_Item")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -19845,15 +19648,15 @@ public void Indexer_Partial_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").SetMethod) - }), + ]), DocumentResults(), ]); @@ -19869,15 +19672,15 @@ public void IndexerInit_Partial_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").SetMethod) - }), + ]), DocumentResults(), ]); @@ -19895,15 +19698,15 @@ public void AutoIndexer_Partial_InsertDelete() // Accessors need to be updated even though they do not have an explicit body. // There is still a sequence point generated for them whose location needs to be updated. EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.this[]").SetMethod), - }), + ]), DocumentResults(), ]); } @@ -19986,13 +19789,13 @@ readonly struct S // Updates only for accessors whose modifiers were explicitly updated. // Indexers themselves are only updated when their modifiers change. The update is not necessary and could be eliminated. - edits.VerifySemantics(new[] - { + edits.VerifySemantics( + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("S.this[]").Single(m => m.Parameters is [{ Type.SpecialType: SpecialType.System_UInt32 }]).GetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("S.this[]").Single(m => m.Parameters is [{ Type.SpecialType: SpecialType.System_Byte }]).SetMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("S.this[]").Single(m => m.Parameters is [{ Type.SpecialType: SpecialType.System_Int32 }])), SemanticEdit(SemanticEditKind.Update, c => c.GetMembers("S.this[]").Single(m => m.Parameters is [{ Type.SpecialType: SpecialType.System_SByte }])), - }); + ]); } #endregion @@ -20080,10 +19883,9 @@ public void Event_Insert() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("E")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -20096,12 +19898,11 @@ public void Event_Delete_CustomAccessors() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.add_E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.remove_E"), deletedSymbolContainerProvider: c => c.GetMember("C")), - }, + ], capabilities: EditAndContinueCapabilities.Baseline); } @@ -20240,14 +20041,14 @@ public void Event_Partial_InsertDelete() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("E").AddMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("E").RemoveMethod) - }), + ]), DocumentResults(), ]); @@ -20327,10 +20128,9 @@ class C capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -20358,12 +20158,11 @@ [System.Obsolete]event Action F { add {} remove {} } capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").AddMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").RemoveMethod) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -20391,7 +20190,7 @@ event Action F { add {} [System.Obsolete]remove {} } capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").RemoveMethod) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").RemoveMethod)], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -20419,7 +20218,7 @@ class C capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -20447,12 +20246,11 @@ event Action F { add {} remove {} } capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").AddMethod), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").RemoveMethod) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -20480,10 +20278,9 @@ event Action F { add {} remove {} } capabilities: EditAndContinueCapabilities.Baseline); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F").RemoveMethod) - }, + ], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -20530,15 +20327,14 @@ public void Event_Rename_CustomAcccessors() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.add_E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.remove_E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.add_F")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.remove_F")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -20568,14 +20364,13 @@ public void Event_Update_Type_CustomAcccessors() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.E")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.add_E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.remove_E"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.add_E")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.remove_E")), - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -20637,13 +20432,13 @@ public void Event_Partial_InsertDelete_SynthesizedAccessors() var srcB2 = "partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetParameterlessConstructor("C"), partialType: "C", preserveLocalVariables: true) - }), + ]), DocumentResults(), ]); @@ -20664,10 +20459,9 @@ public void Parameter_Rename_Method() "Update [int a]@24 -> [int b]@24"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -20688,10 +20482,9 @@ public void Parameter_Rename_Constructor() "Update [int a]@19 -> [int b]@19"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -20735,10 +20528,10 @@ public void Parameter_Insert() "Insert [int a]@24"); edits.VerifySemantics( - new[] { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 0)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 1)?.ISymbol) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -20754,10 +20547,10 @@ public void Parameter_Insert_Ref() "Insert [ref int b]@31"); edits.VerifySemantics( - new[] { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 1)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 2)?.ISymbol) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -20773,10 +20566,10 @@ public void Parameter_Insert_WithUpdatedReturnType() "Insert [int a]@23"); edits.VerifySemantics( - new[] { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -20791,10 +20584,10 @@ public void Parameter_Delete1() "Delete [int a]@24"); edits.VerifySemantics( - new[] { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 1)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 0)?.ISymbol) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -20810,10 +20603,10 @@ public void Parameter_Delete2() "Delete [int a]@24"); edits.VerifySemantics( - new[] { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 2)?.ISymbol, deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMembers("C.M").FirstOrDefault(m => m.GetParameterCount() == 1)?.ISymbol) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } @@ -20828,10 +20621,9 @@ public void Parameter_Reorder() "Reorder [int b]@31 -> @24"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -20841,8 +20633,7 @@ public void Parameter_Reorder() capabilities: EditAndContinueCapabilities.Baseline); } - [Fact] - [WorkItem(67268, "https://github.com/dotnet/roslyn/issues/67268")] + [Fact, WorkItem(67268, "https://github.com/dotnet/roslyn/issues/67268")] public void Parameter_Reorder_Constructor() { var src1 = @"class C { C(int a, int b) {} }"; @@ -20853,10 +20644,9 @@ public void Parameter_Reorder_Constructor() "Reorder [int b]@19 -> @12"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -20878,10 +20668,9 @@ public void Parameter_Reorder_UpdateBody() "Reorder [int b]@31 -> @24"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -20901,11 +20690,10 @@ public void Parameter_Reorder_DifferentTypes() "Reorder [int b]@34 -> @24"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.M"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -20925,10 +20713,9 @@ public void Parameter_Reorder_Rename() "Update [int a]@24 -> [int c]@31"); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters); edits.VerifySemanticDiagnostics( @@ -20948,10 +20735,9 @@ public void Parameter_Reorder_Rename_Generic() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) - }, + ], capabilities: EditAndContinueCapabilities.UpdateParameters | EditAndContinueCapabilities.GenericAddMethodToExistingType | @@ -20987,11 +20773,10 @@ public void Parameter_Update_TypeOrRefKind_RuntimeTypeChanged(string oldType) var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] - { + [ SemanticEdit(SemanticEditKind.Delete, c => c.GetMember("C.F"), deletedSymbolContainerProvider: c => c.GetMember("C")), SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C.F")) - }, + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); edits.VerifySemanticDiagnostics( @@ -21094,7 +20879,7 @@ public void Parameter_Initializer_InsertDeleteUpdate() var srcB2 = @"partial class C { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults( diagnostics: @@ -21119,7 +20904,7 @@ public void Parameter_Attribute_Insert() "Update [int a]@63 -> [[A]int a]@63"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.M"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -21248,7 +21033,7 @@ public void Parameter_Attribute_Update() "Update [[A(0)]int a]@67 -> [[A(1)]int a]@67"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -21267,7 +21052,7 @@ public void Parameter_Attribute_Update_WithBodyUpdate() "Update [[A(0)]int a]@67 -> [[A(1)]int a]@67"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F")) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"))], capabilities: EditAndContinueCapabilities.ChangeCustomAttributes); } @@ -21756,7 +21541,7 @@ class B : System.Attribute {} var srcB2 = "partial class C<[B]T> { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(diagnostics: [ @@ -21785,16 +21570,16 @@ class B : System.Attribute {} var srcB2 = "partial class C<[B]T> { }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ - DocumentResults(semanticEdits: new[] - { + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), - DocumentResults(semanticEdits: new[] - { + ]), + DocumentResults(semanticEdits: + [ SemanticEdit(SemanticEditKind.Replace, c => c.GetMember("C"), partialType: "C") - }), + ]), ], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -21859,10 +21644,10 @@ public void TypeConstraint_Update_RuntimeTypeUnchanged(string oldType, string ne var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - semanticEdits: new[] - { + semanticEdits: + [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C")) - }); + ]); } [Theory] @@ -22021,7 +21806,7 @@ public void TopLevelStatements_Insert_NoImplicitMain() edits.VerifyEdits("Insert [Console.WriteLine(\"Hello World\");]@19"); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("Program.
$")) }, + [SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("Program.
$"))], capabilities: EditAndContinueCapabilities.NewTypeDefinition); } @@ -22237,7 +22022,7 @@ public void TopLevelStatements_Await_Insert_Second() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -22287,7 +22072,7 @@ public void TopLevelStatements_Await_Delete_Second() var edits = GetTopEdits(src1, src2); edits.VerifySemantics( - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), preserveLocalVariables: true) }, + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), preserveLocalVariables: true)], capabilities: EditAndContinueCapabilities.AddInstanceFieldToExistingType); edits.VerifySemanticDiagnostics( @@ -22582,7 +22367,7 @@ public void TopLevelStatements_WithLambda_Insert() edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), syntaxMap[0])]); } [Fact] @@ -22613,7 +22398,7 @@ public class C { } edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), syntaxMap[0])]); } [Fact] @@ -22642,7 +22427,7 @@ public class C { } edits.VerifySemantics( ActiveStatementsDescription.Empty, - new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), syntaxMap[0]) }); + [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"), syntaxMap[0])]); } [Fact] @@ -22705,10 +22490,10 @@ public class B }"; EditAndContinueValidation.VerifySemantics( - new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) }, + [GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)], [ DocumentResults(), - DocumentResults(semanticEdits: new [] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$")) }), + DocumentResults(semanticEdits: [SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.
$"))]), ]); } diff --git a/src/Features/CSharpTest/ExtractClass/ExtractClassTests.cs b/src/Features/CSharpTest/ExtractClass/ExtractClassTests.cs index 39d6de3921b37..dc4874b417b72 100644 --- a/src/Features/CSharpTest/ExtractClass/ExtractClassTests.cs +++ b/src/Features/CSharpTest/ExtractClass/ExtractClassTests.cs @@ -2904,8 +2904,7 @@ public void M() }.RunAsync(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/63315")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/63315")] public async Task TestMethodInsideNamespace_NoException() { var code = """ @@ -2937,8 +2936,7 @@ public void $$N }.RunAsync(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/55610")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/55610")] public async Task TestMultipleMethodsSelected_WithTypeContainingBaseClass() { var code = """ @@ -2960,8 +2958,7 @@ public void N() { }|] }.RunAsync(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/55610")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/55610")] public async Task TestClassSelected_WithTypeContainingBaseClass() { var code = """ @@ -3025,8 +3022,7 @@ public void N() { } }.RunAsync(); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/55402")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/55402")] public async Task TestMemberKeyword() { var code = """ diff --git a/src/Features/CSharpTest/ExtractMethod/ExtractLocalFunctionTests.cs b/src/Features/CSharpTest/ExtractMethod/ExtractLocalFunctionTests.cs index 83e534311f547..a2fcc782a0aaa 100644 --- a/src/Features/CSharpTest/ExtractMethod/ExtractLocalFunctionTests.cs +++ b/src/Features/CSharpTest/ExtractMethod/ExtractLocalFunctionTests.cs @@ -1713,7 +1713,7 @@ void NewMethod() } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_local_function]); await TestInRegularAndScript1Async(code, expectedCode, CodeActionIndexWhenExtractMethodMissing); } @@ -1864,7 +1864,7 @@ void NewMethod() } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_local_function]); await TestInRegularAndScript1Async(code, expectedCode, CodeActionIndexWhenExtractMethodMissing); } @@ -4116,7 +4116,7 @@ static void Main(string[] args) } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }, new TestParameters(parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6))); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method], new TestParameters(parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6))); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -4132,7 +4132,7 @@ static void Main(string[] args) } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }, new TestParameters(parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5))); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method], new TestParameters(parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5))); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -4952,7 +4952,7 @@ class Program public int Blah => [|this.field|]; } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method]); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -4966,7 +4966,7 @@ class Program public int this[int i] => [|this.field|]; } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method]); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -4984,7 +4984,7 @@ public int Blah } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method]); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -5002,7 +5002,7 @@ public int Blah } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method]); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -5020,7 +5020,7 @@ public int this[int i] } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method]); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] @@ -5038,7 +5038,7 @@ public int this[int i] } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_method }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_method]); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractLocalFunction)] diff --git a/src/Features/CSharpTest/ExtractMethod/ExtractMethodTests2.cs b/src/Features/CSharpTest/ExtractMethod/ExtractMethodTests2.cs index 00fd059fac848..c7709d46549da 100644 --- a/src/Features/CSharpTest/ExtractMethod/ExtractMethodTests2.cs +++ b/src/Features/CSharpTest/ExtractMethod/ExtractMethodTests2.cs @@ -1961,7 +1961,7 @@ void Local() { } } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_local_function]); } [Fact] @@ -2006,7 +2006,7 @@ public static void Main(string[] args) } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_local_function]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/15532")] @@ -3846,7 +3846,7 @@ static void Local() } } """; - await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function }); + await TestExactActionSetOfferedAsync(code, [FeaturesResources.Extract_local_function]); } [Fact] diff --git a/src/Features/CSharpTest/GenerateMethod/GenerateMethodTests.cs b/src/Features/CSharpTest/GenerateMethod/GenerateMethodTests.cs index 378badcf86172..b2cc79eb81416 100644 --- a/src/Features/CSharpTest/GenerateMethod/GenerateMethodTests.cs +++ b/src/Features/CSharpTest/GenerateMethod/GenerateMethodTests.cs @@ -8036,8 +8036,7 @@ private static int i() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/643")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/643")] [WorkItem("https://github.com/dotnet/roslyn/issues/14467")] public async Task TestGenerateMethodWithConfigureAwaitFalse() { @@ -8077,8 +8076,7 @@ private static async Task Goo() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/643")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/643")] [WorkItem("https://github.com/dotnet/roslyn/issues/14467")] public async Task TestGenerateMethodWithMethodChaining() { @@ -8118,8 +8116,7 @@ private static async Task Goo() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/643")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/643")] [WorkItem("https://github.com/dotnet/roslyn/issues/14467")] public async Task TestGenerateMethodWithMethodChaining2() { @@ -10842,4 +10839,255 @@ private static void Goo() } """); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple1() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x, y, ) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x, y, ) = NewExpr(); + } + + private object NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple2() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x, y, , z) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x, y, , z) = NewExpr(); + } + + private object NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple3() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x, y, 0) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x, y, 0) = NewExpr(); + } + + private object NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple4() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x, y, (z, w)) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x, y, (z, w)) = NewExpr(); + } + + private (object x, object y, (object z, object w)) NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple5() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x, y, (z, w, )) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x, y, (z, w, )) = NewExpr(); + } + + private object NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple6() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x, y, (z, w), ) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x, y, (z, w), ) = NewExpr(); + } + + private object NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple7() + { + await TestMissingInRegularAndScriptAsync( + """ + using System; + using System.Threading.Tasks; + + class C + { + async Task M() + { + var ([|NewExpr|]) = await G(); + } + + Task<(int, string)> G() => default; + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71980")] + public async Task AssignToTuple8() + { + await TestInRegularAndScriptAsync( + """ + using System; + + class C + { + int M() + { + var (x) = [|NewExpr()|]; + } + } + """, + """ + using System; + + class C + { + int M() + { + var (x) = NewExpr(); + } + + private (object x, object) NewExpr() + { + throw new NotImplementedException(); + } + } + """); + } } diff --git a/src/Features/CSharpTest/GenerateVariable/GenerateVariableTests.cs b/src/Features/CSharpTest/GenerateVariable/GenerateVariableTests.cs index 8ca87e64aae55..98761be4d666f 100644 --- a/src/Features/CSharpTest/GenerateVariable/GenerateVariableTests.cs +++ b/src/Features/CSharpTest/GenerateVariable/GenerateVariableTests.cs @@ -92,14 +92,13 @@ void Method() } } """, -new[] -{ +[ string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_read_only_field_0, "goo"), string.Format(FeaturesResources.Generate_property_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo"), -}); +]); } [Fact] @@ -115,11 +114,10 @@ void Method() } } """, -new[] -{ +[ string.Format(FeaturesResources.Generate_field_0, "_goo"), string.Format(FeaturesResources.Generate_read_only_field_0, "_goo"), -}); +]); } [Fact] @@ -359,7 +357,7 @@ void Method(int i) } } """, -new[] { string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_property_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo") }); +[string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_property_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo")]); } [Fact] @@ -380,7 +378,7 @@ public override void Method(int i) } } """, -new[] { string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_property_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0_and_overrides_implementations, "goo") }); +[string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_property_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0_and_overrides_implementations, "goo")]); } [Fact] @@ -557,7 +555,7 @@ void Method(out int i) } } """, -new[] { string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo") }); +[string.Format(FeaturesResources.Generate_field_0, "goo"), string.Format(FeaturesResources.Generate_local_0, "goo"), string.Format(FeaturesResources.Generate_parameter_0, "goo")]); } [Fact] @@ -2434,7 +2432,7 @@ static void Main() } } """, -new[] { string.Format(FeaturesResources.Generate_field_0, "p"), string.Format(FeaturesResources.Generate_property_0, "p"), string.Format(FeaturesResources.Generate_local_0, "p"), string.Format(FeaturesResources.Generate_parameter_0, "p") }); +[string.Format(FeaturesResources.Generate_field_0, "p"), string.Format(FeaturesResources.Generate_property_0, "p"), string.Format(FeaturesResources.Generate_local_0, "p"), string.Format(FeaturesResources.Generate_parameter_0, "p")]); await TestInRegularAndScriptAsync( """ @@ -5323,7 +5321,7 @@ void Goo() #line hidden } """; - await TestExactActionSetOfferedAsync(code, new[] { string.Format(FeaturesResources.Generate_local_0, "Bar"), string.Format(FeaturesResources.Generate_parameter_0, "Bar") }); + await TestExactActionSetOfferedAsync(code, [string.Format(FeaturesResources.Generate_local_0, "Bar"), string.Format(FeaturesResources.Generate_parameter_0, "Bar")]); await TestInRegularAndScriptAsync(code, """ @@ -10552,11 +10550,11 @@ public C() }; } } - """, new[] -{ + """, +[ string.Format(FeaturesResources.Generate_property_0, "Field"), string.Format(FeaturesResources.Generate_field_0, "Field"), -}); +]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26502")] @@ -10576,11 +10574,11 @@ void Goo() }; } } - """, new[] -{ + """, +[ string.Format(FeaturesResources.Generate_property_0, "Field"), string.Format(FeaturesResources.Generate_field_0, "Field"), -}); +]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45367")] @@ -10599,11 +10597,11 @@ internal MyException(int error, int offset, string message) : base(message) [|Error|] = error; Offset = offset; } - """, new[] -{ + """, +[ string.Format(FeaturesResources.Generate_local_0, "Error", "MyException"), string.Format(FeaturesResources.Generate_parameter_0, "Error", "MyException"), -}); +]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48172")] diff --git a/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs index d80f3e05d08cb..543d5c76f09e3 100644 --- a/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs +++ b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs @@ -148,6 +148,41 @@ protected override (int a, int b) Method((string, string d) x) """); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/70623")] + public async Task TestMethodWithNullableDynamic() + { + await TestInRegularAndScriptAsync( + """ + abstract class Base + { + public abstract dynamic? M(dynamic? arg); + } + + class [|Program|] : Base + { + } + """, + """ + abstract class Base + { + public abstract dynamic? M(dynamic? arg); + } + + class Program : Base + { + public override dynamic? M(dynamic? arg) + { + throw new System.NotImplementedException(); + } + } + """, + compilationOptions: new CSharpCompilationOptions + ( + OutputKind.DynamicallyLinkedLibrary, + nullableContextOptions: NullableContextOptions.Enable + )); + } + [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543234")] public async Task TestNotAvailableForStruct() { diff --git a/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs index 20bfcbbacc060..a57f7d100222e 100644 --- a/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs +++ b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs @@ -72,7 +72,7 @@ abstract class Base class [|Derived|] : Base { } - """, new[] { FeaturesResources.Implement_abstract_class }); + """, [FeaturesResources.Implement_abstract_class]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41420")] @@ -93,7 +93,7 @@ abstract class Middle : Base class [|Derived|] : Base { } - """, new[] { FeaturesResources.Implement_abstract_class }); + """, [FeaturesResources.Implement_abstract_class]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41420")] @@ -345,12 +345,12 @@ class [|Derived|] : Base, IInterface Base IInterface.Inner { get; } } - """, new[] -{ + """, +[ FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "Inner"), string.Format(FeaturesResources.Implement_through_0, "IInterface.Inner"), -}); +]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41420")] @@ -367,7 +367,7 @@ class [|Derived|] : Base { dynamic inner; } - """, new[] { FeaturesResources.Implement_abstract_class }); + """, [FeaturesResources.Implement_abstract_class]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41420")] @@ -650,7 +650,7 @@ class [|Derived|] : Base { Base inner; } - """, new[] { FeaturesResources.Implement_abstract_class }); + """, [FeaturesResources.Implement_abstract_class]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41420")] @@ -766,7 +766,7 @@ class [|Derived|] : Base { Base inner; } - """, new[] { FeaturesResources.Implement_abstract_class }); + """, [FeaturesResources.Implement_abstract_class]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/41420")] @@ -935,7 +935,7 @@ class [|Program|](Base base1) : Base { private Base _base = base1; } - """, new[] { FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "_base") }); + """, [FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "_base")]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69177")] @@ -953,7 +953,7 @@ class [|Program|](Base base1) : Base { private Base _base = (base1); } - """, new[] { FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "_base") }); + """, [FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "_base")]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69177")] @@ -971,7 +971,7 @@ class [|Program|](Base base1) : Base { private Base B { get; } = base1; } - """, new[] { FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "B") }); + """, [FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "B")]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69177")] @@ -989,7 +989,7 @@ class [|Program|](Base base1) : Base { private Base B { get; } = (base1); } - """, new[] { FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "B") }); + """, [FeaturesResources.Implement_abstract_class, string.Format(FeaturesResources.Implement_through_0, "B")]); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69177")] diff --git a/src/Features/CSharpTest/IntroduceVariable/IntroduceVariableTests.cs b/src/Features/CSharpTest/IntroduceVariable/IntroduceVariableTests.cs index eee0c0ffe3721..82cf8a801c445 100644 --- a/src/Features/CSharpTest/IntroduceVariable/IntroduceVariableTests.cs +++ b/src/Features/CSharpTest/IntroduceVariable/IntroduceVariableTests.cs @@ -2134,7 +2134,7 @@ void Main ( ) } """; - await TestExactActionSetOfferedAsync(code, new[] { string.Format(FeaturesResources.Introduce_local_constant_for_0, "5") }); + await TestExactActionSetOfferedAsync(code, [string.Format(FeaturesResources.Introduce_local_constant_for_0, "5")]); await TestInRegularAndScriptAsync(code, """ @@ -2176,7 +2176,7 @@ void Main ( ) """; await TestExactActionSetOfferedAsync(code, - new[] { string.Format(FeaturesResources.Introduce_local_constant_for_0, "5"), string.Format(FeaturesResources.Introduce_local_constant_for_all_occurrences_of_0, "5") }); + [string.Format(FeaturesResources.Introduce_local_constant_for_0, "5"), string.Format(FeaturesResources.Introduce_local_constant_for_all_occurrences_of_0, "5")]); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529795")] diff --git a/src/Features/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs b/src/Features/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs index 3620aa3ac5a9a..efbb73e25f3cf 100644 --- a/src/Features/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs +++ b/src/Features/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs @@ -456,8 +456,7 @@ class C """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/22278")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22278")] [WorkItem("https://github.com/dotnet/roslyn/issues/31208")] public async Task TestApplicableKeyword() { diff --git a/src/Features/CSharpTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs b/src/Features/CSharpTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs index cfabec68603bf..90a8f63172b01 100644 --- a/src/Features/CSharpTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs +++ b/src/Features/CSharpTest/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.cs @@ -1442,8 +1442,7 @@ void M() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16157")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16157")] public async Task TestWithConditionalBinding1() { await TestInRegularAndScriptAsync( @@ -1478,8 +1477,7 @@ public static void Bar() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle1() { await TestInRegularAndScriptAsync( @@ -1503,8 +1501,7 @@ class C """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle2() { await TestInRegularAndScriptAsync( @@ -1534,8 +1531,7 @@ class C """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle3() { await TestInRegularAndScriptAsync( @@ -1559,8 +1555,7 @@ class C """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle4() { await TestInRegularAndScriptAsync( @@ -1578,8 +1573,7 @@ class C """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle5() { await TestInRegularAndScriptAsync( @@ -1599,8 +1593,7 @@ class C """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle6() { await TestInRegularAndScriptAsync( @@ -1621,8 +1614,7 @@ class C """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/16980")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16980")] public async Task TestCodeStyle7() { await TestInRegularAndScriptAsync( @@ -1651,8 +1643,7 @@ private int GetProp() """, options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18234")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18234")] public async Task TestDocumentationComment1() { await TestInRegularAndScriptAsync( @@ -1685,8 +1676,7 @@ internal interface ILanguageServiceHost """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18234")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18234")] public async Task TestDocumentationComment2() { await TestInRegularAndScriptAsync( @@ -1719,8 +1709,7 @@ internal interface ILanguageServiceHost """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18234")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18234")] public async Task TestDocumentationComment3() { await TestInRegularAndScriptAsync( @@ -1761,8 +1750,7 @@ internal interface ILanguageServiceHost """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18234")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18234")] public async Task TestDocumentationComment4() { await TestInRegularAndScriptAsync( @@ -1801,8 +1789,7 @@ internal struct AStruct """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18234")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18234")] public async Task TestDocumentationComment5() { await TestInRegularAndScriptAsync( @@ -1847,8 +1834,7 @@ internal struct AStruct """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/18234")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/18234")] public async Task TestDocumentationComment6() { await TestInRegularAndScriptAsync( @@ -1881,8 +1867,7 @@ internal struct AStruct """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/19235")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19235")] public async Task TestWithDirectives1() { await TestInRegularAndScriptAsync( @@ -1917,8 +1902,7 @@ private int GetProp() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/19235")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19235")] public async Task TestWithDirectives2() { await TestInRegularAndScriptAsync( @@ -1952,8 +1936,7 @@ private int GetProp() => options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/19235")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19235")] public async Task TestWithDirectives3() { await TestInRegularAndScriptAsync( @@ -1981,8 +1964,7 @@ private int GetProp() => """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/19235")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/19235")] public async Task TestWithDirectives4() { await TestInRegularAndScriptAsync( @@ -2011,8 +1993,7 @@ private int GetProp() => options: PreferExpressionBodiedMethods); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/440371")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/440371")] public async Task TestExplicitInterfaceImplementation() { await TestInRegularAndScriptAsync( @@ -2059,8 +2040,7 @@ void IGoo.SetGoo(int value) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/38379")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38379")] public async Task TestUnsafeExpressionBody() { await TestInRegularAndScriptAsync( @@ -2081,8 +2061,7 @@ class C """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/38379")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38379")] public async Task TestUnsafeAutoProperty() { await TestInRegularAndScriptAsync( @@ -2110,8 +2089,7 @@ public unsafe void SetPointer(void* value) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/38379")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38379")] public async Task TestUnsafeSafeType() { await TestInRegularAndScriptAsync( @@ -2139,8 +2117,7 @@ public unsafe void SetP(int value) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/22760")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22760")] public async Task QualifyFieldAccessWhenNecessary1() { await TestInRegularAndScriptAsync( @@ -2173,8 +2150,7 @@ public C(int value) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/22760")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22760")] public async Task QualifyFieldAccessWhenNecessary2() { await TestInRegularAndScriptAsync( @@ -2207,8 +2183,7 @@ public C(int value) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/22760")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/22760")] public async Task QualifyFieldAccessWhenNecessary3() { await TestInRegularAndScriptAsync( @@ -2241,8 +2216,7 @@ public static void Set(int value) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/45171")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45171")] public async Task TestReferenceInObjectInitializer() { await TestInRegularAndScriptAsync( @@ -2289,8 +2263,7 @@ void Main() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/45171")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45171")] public async Task TestReferenceInImplicitObjectInitializer() { await TestInRegularAndScriptAsync( @@ -2337,8 +2310,7 @@ void Main() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/45171")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/45171")] public async Task TestReferenceInWithInitializer() { await TestInRegularAndScriptAsync( @@ -2385,8 +2357,7 @@ void Main() """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/57376")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/57376")] public async Task TestInLinkedFile() { await TestInRegularAndScriptAsync( diff --git a/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs b/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs index a496dba59e1bd..2347e3e97a42e 100644 --- a/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs +++ b/src/Features/CSharpTest/SimplifyTypeNames/SimplifyTypeNamesTests.cs @@ -528,8 +528,7 @@ static void Main(string[] args) """); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/21449")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21449")] [WorkItem("https://github.com/dotnet/roslyn/issues/40972")] public async Task DoChangeToAliasInNameOfIfItDoesNotAffectName1() { diff --git a/src/Features/CSharpTest/SpellCheck/SpellCheckTests.cs b/src/Features/CSharpTest/SpellCheck/SpellCheckTests.cs index 6f04da6e3119b..1076c1e87836e 100644 --- a/src/Features/CSharpTest/SpellCheck/SpellCheckTests.cs +++ b/src/Features/CSharpTest/SpellCheck/SpellCheckTests.cs @@ -58,7 +58,7 @@ void Bar() } }"; - await TestExactActionSetOfferedAsync(text, new[] { String.Format(FeaturesResources.Change_0_to_1, "Gooa", "Goo") }); + await TestExactActionSetOfferedAsync(text, [String.Format(FeaturesResources.Change_0_to_1, "Gooa", "Goo")]); } [Fact] @@ -72,11 +72,11 @@ void Bar() } }"; - await TestExactActionSetOfferedAsync(text, new[] - { + await TestExactActionSetOfferedAsync(text, + [ String.Format(FeaturesResources.Change_0_to_1, "Foa", "Foo"), String.Format(FeaturesResources.Change_0_to_1, "Foa", "for") - }); + ]); } [Fact] @@ -92,7 +92,7 @@ void Bar(Func<[|Goa|]> f) } }"; await TestExactActionSetOfferedAsync(text, - new[] { String.Format(FeaturesResources.Change_0_to_1, "Goa", "Goo") }); + [String.Format(FeaturesResources.Change_0_to_1, "Goa", "Goo")]); } [Fact] @@ -106,7 +106,7 @@ void Main(string[] args) var y = 2 + [|zza|]; } }"; - await TestExactActionSetOfferedAsync(text, new[] { String.Format(FeaturesResources.Change_0_to_1, "zza", "zzz") }); + await TestExactActionSetOfferedAsync(text, [String.Format(FeaturesResources.Change_0_to_1, "zza", "zzz")]); } [Fact] @@ -120,11 +120,11 @@ void F() if (x is [|Boolea|]) {} } }"; - await TestExactActionSetOfferedAsync(text, new[] - { + await TestExactActionSetOfferedAsync(text, + [ String.Format(FeaturesResources.Change_0_to_1, "Boolea", "Boolean"), String.Format(FeaturesResources.Change_0_to_1, "Boolea", "bool") - }); + ]); } [Fact] diff --git a/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs b/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs index 126ca8428c25e..ab965154a38c7 100644 --- a/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs @@ -149,7 +149,7 @@ private async Task ApplyAsync(Document document, TTypeDeclarationSynta } var newAttribute = generator - .Attribute(generator.TypeExpression(debuggerAttributeTypeSymbol), new[] { attributeArgument }) + .Attribute(generator.TypeExpression(debuggerAttributeTypeSymbol), [attributeArgument]) .WithAdditionalAnnotations( Simplifier.Annotation, Simplifier.AddImportsAnnotation); @@ -165,13 +165,13 @@ private async Task ApplyAsync(Document document, TTypeDeclarationSynta DebuggerDisplayMethodName, returnType: generator.TypeExpression(SpecialType.System_String), accessibility: Accessibility.Private, - statements: new[] - { + statements: + [ generator.ReturnStatement(generator.InvocationExpression( generator.MemberAccessExpression( generator.ThisExpression(), generator.IdentifierName("ToString")))) - })); + ])); } return document.WithSyntaxRoot(editor.GetChangedRoot()); diff --git a/src/Features/Core/Portable/AddPackage/InstallPackageParentCodeAction.cs b/src/Features/Core/Portable/AddPackage/InstallPackageParentCodeAction.cs index 65b660280b825..b2e32c946522f 100644 --- a/src/Features/Core/Portable/AddPackage/InstallPackageParentCodeAction.cs +++ b/src/Features/Core/Portable/AddPackage/InstallPackageParentCodeAction.cs @@ -48,21 +48,19 @@ private static ImmutableArray CreateNestedActions( // in this solution. We'll offer to add those specific versions to this project, // followed by an option to "Find and install latest version." var installedVersions = installerService.GetInstalledVersions(packageName); - var codeActions = ArrayBuilder.GetInstance(); - - // First add the actions to install a specific version. - codeActions.AddRange(installedVersions.Select(v => CreateCodeAction( - installerService, source, packageName, document, - versionOpt: v, includePrerelease: includePrerelease, isLocal: true))); - - // Now add the action to install the specific version. - codeActions.Add(CreateCodeAction( - installerService, source, packageName, document, - versionOpt: null, includePrerelease: includePrerelease, isLocal: false)); - - // And finally the action to show the package manager dialog. - codeActions.Add(new InstallWithPackageManagerCodeAction(installerService, packageName)); - return codeActions.ToImmutableAndFree(); + return + [ + // First add the actions to install a specific version. + .. installedVersions.Select(v => CreateCodeAction( + installerService, source, packageName, document, + versionOpt: v, includePrerelease: includePrerelease, isLocal: true)), + // Now add the action to install the specific version. + CreateCodeAction( + installerService, source, packageName, document, + versionOpt: null, includePrerelease: includePrerelease, isLocal: false), + // And finally the action to show the package manager dialog. + new InstallWithPackageManagerCodeAction(installerService, packageName), + ]; } private static CodeAction CreateCodeAction( diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaHelpers.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaHelpers.cs index c32448f455f6d..79616a4837679 100644 --- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaHelpers.cs +++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaHelpers.cs @@ -55,7 +55,7 @@ internal static async Task GetChangeDocumentWithPragmaAdjustedAsync( } else { - newNode = nodeWithTokens.ReplaceTokens(new[] { startToken, endToken }, (o, n) => o == startToken ? newStartToken : newEndToken); + newNode = nodeWithTokens.ReplaceTokens([startToken, endToken], (o, n) => o == startToken ? newStartToken : newEndToken); } var newRoot = root.ReplaceNode(nodeWithTokens, newNode); @@ -238,7 +238,7 @@ internal static void NormalizeTriviaOnTokens(AbstractSuppressionCodeFixProvider var newPreviousOfStart = previousOfStart.WithTrailingTrivia(); var newNextOfEnd = nextOfEnd.WithLeadingTrivia(); - var newSubtreeRoot = subtreeRoot.ReplaceTokens(new[] { startToken, previousOfStart, endToken, nextOfEnd }, + var newSubtreeRoot = subtreeRoot.ReplaceTokens([startToken, previousOfStart, endToken, nextOfEnd], (o, n) => { if (o == currentStartToken) diff --git a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs index 98d09f1b92e44..7969c1e510404 100644 --- a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs @@ -178,7 +178,7 @@ private async Task CleanUpNewLinesAsync(Document document, TextSpan in var textChanges = Formatter.GetFormattedTextChanges( root, - new[] { insertSpan }, + [insertSpan], services, options: options, rules: GetFormatRules(text), diff --git a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeNamespaceScopeEditor.cs b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeNamespaceScopeEditor.cs index 27b1bcd84c088..e4f2fff578a7d 100644 --- a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeNamespaceScopeEditor.cs +++ b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeNamespaceScopeEditor.cs @@ -71,7 +71,7 @@ private static async Task GetNamespaceScopeChangedSolutionAsync( editor.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepNoTrivia); } - editor.InsertAfter(namespaceDeclaration, new[] { newNamespaceDeclaration, itemsAfterNamespaceDeclaration }); + editor.InsertAfter(namespaceDeclaration, [newNamespaceDeclaration, itemsAfterNamespaceDeclaration]); } else if (itemsBefore.Any()) { diff --git a/src/Features/Core/Portable/Common/FeaturesSessionTelemetry.cs b/src/Features/Core/Portable/Common/FeaturesSessionTelemetry.cs index 19fc302749750..d434041ae9c6d 100644 --- a/src/Features/Core/Portable/Common/FeaturesSessionTelemetry.cs +++ b/src/Features/Core/Portable/Common/FeaturesSessionTelemetry.cs @@ -2,14 +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.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.CodeAnalysis.ChangeSignature; using Microsoft.CodeAnalysis.Completion.Log; -using Microsoft.CodeAnalysis.Logging; namespace Microsoft.CodeAnalysis.Common { @@ -18,7 +12,6 @@ internal static class FeaturesSessionTelemetry public static void Report() { CompletionProvidersLogger.ReportTelemetry(); - SolutionLogger.ReportTelemetry(); ChangeSignatureLogger.ReportTelemetry(); } } diff --git a/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs b/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs index 852bd8cc04b2a..5f5fec8585994 100644 --- a/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs +++ b/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs @@ -91,7 +91,7 @@ public static Func> CreateDescrip ISymbol symbol, SymbolDescriptionOptions options) { - return CreateDescriptionFactory(workspaceServices, semanticModel, position, options, new[] { symbol }); + return CreateDescriptionFactory(workspaceServices, semanticModel, position, options, [symbol]); } public static Func> CreateDescriptionFactory( diff --git a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs index 0d9cc2726ff06..f450afb5e8c06 100644 --- a/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs +++ b/src/Features/Core/Portable/Completion/CompletionService.ProviderManager.cs @@ -134,18 +134,17 @@ private ImmutableArray GetImportedAndBuiltInProviders(Immuta ImmutableArray GetImportedAndBuiltInProvidersWorker(ImmutableHashSet roles) { - using var _ = ArrayBuilder.GetInstance(out var providers); - providers.AddRange(GetLazyImportedProviders() - .Where(lz => lz.Metadata.Roles == null || lz.Metadata.Roles.Length == 0 || roles.Overlaps(lz.Metadata.Roles)) - .Select(lz => lz.Value)); - + return + [ + .. GetLazyImportedProviders() + .Where(lz => lz.Metadata.Roles == null || lz.Metadata.Roles.Length == 0 || roles.Overlaps(lz.Metadata.Roles)) + .Select(lz => lz.Value), + // We need to keep supporting built-in providers for a while longer since this is a public API. + // https://github.com/dotnet/roslyn/issues/42367 #pragma warning disable 0618 - // We need to keep supporting built-in providers for a while longer since this is a public API. - // https://github.com/dotnet/roslyn/issues/42367 - providers.AddRange(_service.GetBuiltInProviders()); + .. _service.GetBuiltInProviders(), #pragma warning restore 0618 - - return providers.ToImmutable(); + ]; } } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs index 07b48579570a4..c4eb2d0e37d92 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractDocCommentCompletionProvider.cs @@ -120,7 +120,7 @@ protected IEnumerable GetAttributeItems(string tagName, ISet GetAlwaysVisibleItems() - => new[] { GetCDataItem(), GetCommentItem(), GetItem(InheritdocElementName), GetItem(SeeElementName), GetItem(SeeAlsoElementName) }; + => [GetCDataItem(), GetCommentItem(), GetItem(InheritdocElementName), GetItem(SeeElementName), GetItem(SeeAlsoElementName)]; private CompletionItem GetCommentItem() { diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.SymbolComputer.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.SymbolComputer.cs index e0d60f876efaa..1bd00606b14ab 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.SymbolComputer.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.SymbolComputer.cs @@ -516,12 +516,12 @@ static void AddNamesForTypeWorker(ITypeSymbol receiverTypeSymbol, PooledHashSet< ///
private static ImmutableArray AddComplexTypes(ImmutableArray receiverTypeNames) { - using var _ = ArrayBuilder.GetInstance(receiverTypeNames.Length + 2, out var receiverTypeNamesBuilder); - receiverTypeNamesBuilder.AddRange(receiverTypeNames); - receiverTypeNamesBuilder.Add(FindSymbols.Extensions.ComplexReceiverTypeName); - receiverTypeNamesBuilder.Add(FindSymbols.Extensions.ComplexArrayReceiverTypeName); - - return receiverTypeNamesBuilder.ToImmutableAndClear(); + return + [ + .. receiverTypeNames, + FindSymbols.Extensions.ComplexReceiverTypeName, + FindSymbols.Extensions.ComplexArrayReceiverTypeName, + ]; } private static string GetReceiverTypeName(ITypeSymbol typeSymbol) diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs index 2a2eebaba439c..64b1b0b95bee5 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs @@ -113,13 +113,13 @@ public static async Task GetUnimportedEx // Workspace's syntax/symbol index is used to avoid iterating every method symbols in the solution. var symbolComputer = await SymbolComputer.CreateAsync( document, position, receiverTypeSymbol, namespaceInScope, cancellationToken).ConfigureAwait(false); - var (extentsionMethodSymbols, isPartialResult) = await symbolComputer.GetExtensionMethodSymbolsAsync(forceCacheCreation, hideAdvancedMembers, cancellationToken).ConfigureAwait(false); + var (extensionMethodSymbols, isPartialResult) = await symbolComputer.GetExtensionMethodSymbolsAsync(forceCacheCreation, hideAdvancedMembers, cancellationToken).ConfigureAwait(false); var getSymbolsTime = stopwatch.Elapsed; stopwatch = SharedStopwatch.StartNew(); var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); - var items = ConvertSymbolsToCompletionItems(compilation, extentsionMethodSymbols, targetTypes, cancellationToken); + var items = ConvertSymbolsToCompletionItems(compilation, extensionMethodSymbols, targetTypes, cancellationToken); var createItemsTime = stopwatch.Elapsed; diff --git a/src/Features/Core/Portable/ConvertLinq/AbstractConvertLinqQueryToForEachProvider.cs b/src/Features/Core/Portable/ConvertLinq/AbstractConvertLinqQueryToForEachProvider.cs index 49ae178f743cb..28935e16793de 100644 --- a/src/Features/Core/Portable/ConvertLinq/AbstractConvertLinqQueryToForEachProvider.cs +++ b/src/Features/Core/Portable/ConvertLinq/AbstractConvertLinqQueryToForEachProvider.cs @@ -61,7 +61,7 @@ internal sealed class DocumentUpdateInfo(TStatement source, IEnumerable Destinations = ImmutableArray.CreateRange(destinations); - public DocumentUpdateInfo(TStatement source, TStatement destination) : this(source, new[] { destination }) + public DocumentUpdateInfo(TStatement source, TStatement destination) : this(source, [destination]) { } diff --git a/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs b/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs index a5ff998dadae2..0af5304808548 100644 --- a/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertToInterpolatedString/ConvertRegularStringToInterpolatedStringRefactoringProvider.cs @@ -100,7 +100,7 @@ private static SyntaxNode CreateInterpolatedString(Document document, SyntaxNode return generator.InterpolatedStringExpression( generator.CreateInterpolatedStringStartToken(isVerbatim), - new[] { newNode }, + [newNode], generator.CreateInterpolatedStringEndToken()).WithTriviaFrom(literalExpression); } diff --git a/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs b/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs index 3ad60f8632db1..72dbf8668957a 100644 --- a/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs +++ b/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs @@ -266,11 +266,7 @@ private static async Task> CreateSpansAsync( using var _1 = ArrayBuilder.GetInstance(tagMap.Count, out var list); foreach (var kvp in tagMap) { - using var _2 = ArrayBuilder.GetInstance(kvp.Value.Count, out var spans); - foreach (var span in kvp.Value) - spans.Add(span); - - list.Add(new DocumentHighlights(kvp.Key, spans.ToImmutableAndClear())); + list.Add(new DocumentHighlights(kvp.Key, [.. kvp.Value])); } return list.ToImmutableAndClear(); diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs index 438bd7682517f..d54eb66e984f7 100644 --- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs +++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs @@ -1203,7 +1203,7 @@ private void AnalyzeChangedMemberBody( // Lambda containing the active statement can't be found in the new source. var oldLambda = oldEnclosingLambdaBody.GetLambda(); diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.ActiveStatementLambdaRemoved, newSpan, oldLambda, - new[] { GetDisplayName(oldLambda) })); + [GetDisplayName(oldLambda)])); } else { @@ -1215,7 +1215,7 @@ private void AnalyzeChangedMemberBody( diagnostics.Add( new RudeEditDiagnostic(isNonLeaf ? RudeEditKind.DeleteActiveStatement : RudeEditKind.PartiallyExecutedActiveStatementDelete, GetDeletedNodeDiagnosticSpan(enclosingBodyMap.Forward, oldStatementSyntax), - arguments: new[] { FeaturesResources.code })); + arguments: [FeaturesResources.code])); } } @@ -1271,11 +1271,11 @@ private void AnalyzeChangedMemberBody( // it might throw another OOM here or later on. if (e is OutOfMemoryException) { - diagnosticContext.Report(RudeEditKind.MemberBodyTooBig, cancellationToken, arguments: new[] { newMember.Name }); + diagnosticContext.Report(RudeEditKind.MemberBodyTooBig, cancellationToken, arguments: [newMember.Name]); } else { - diagnosticContext.Report(RudeEditKind.MemberBodyInternalError, cancellationToken, arguments: new[] { newMember.Name, e.ToString() }); + diagnosticContext.Report(RudeEditKind.MemberBodyInternalError, cancellationToken, arguments: [newMember.Name, e.ToString()]); } syntaxMaps = new SyntaxMaps(newModel.SyntaxTree); @@ -1325,7 +1325,7 @@ private ActiveStatement GetActiveStatementWithSpan(UnmappedActiveStatement oldSt RudeEditKind.UpdateAroundActiveStatement, newSpan, LineDirectiveSyntaxKind, - arguments: new[] { string.Format(FeaturesResources._0_directive, LineDirectiveKeyword) })); + arguments: [string.Format(FeaturesResources._0_directive, LineDirectiveKeyword)])); } return oldStatement.Statement.WithFileSpan(mappedLineSpan); @@ -1771,7 +1771,7 @@ protected void AddRudeUpdateAroundActiveStatement(ArrayBuilder diagnostics, SyntaxNode newNode) @@ -1780,7 +1780,7 @@ protected void AddRudeInsertAroundActiveStatement(ArrayBuilder diagnostics, SyntaxNode oldNode, TextSpan newActiveStatementSpan) @@ -1789,7 +1789,7 @@ protected void AddRudeDeleteAroundActiveStatement(ArrayBuilder( @@ -2513,7 +2513,7 @@ private async Task> AnalyzeSemanticsAsync( RudeEditKind.ChangingNamespace, GetDiagnosticSpan(newTypeDeclaration, EditKind.Update), newTypeDeclaration, - new[] { GetDisplayName(newTypeDeclaration), oldSymbol.ContainingNamespace.ToDisplayString(), newSymbol.ContainingNamespace.ToDisplayString() })); + [GetDisplayName(newTypeDeclaration), oldSymbol.ContainingNamespace.ToDisplayString(), newSymbol.ContainingNamespace.ToDisplayString()])); } else { @@ -2674,7 +2674,7 @@ newSymbol is IPropertySymbol newProperty && // If we got here for a global statement then the actual edit is a delete of the synthesized Main method if (IsGlobalMain(oldSymbol)) { - diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.Delete, diagnosticSpan, edit.OldNode, new[] { GetDisplayName(edit.OldNode!, EditKind.Delete) })); + diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.Delete, diagnosticSpan, edit.OldNode, [GetDisplayName(edit.OldNode!, EditKind.Delete)])); continue; } @@ -2691,7 +2691,7 @@ newSymbol is IPropertySymbol newProperty && rudeEditKind, diagnosticSpan, oldDeclaration, - new[] { GetDisplayKindAndName(oldSymbol, GetDisplayName(oldDeclaration, EditKind.Delete), fullyQualify: diagnosticSpan.IsEmpty) })); + [GetDisplayKindAndName(oldSymbol, GetDisplayName(oldDeclaration, EditKind.Delete), fullyQualify: diagnosticSpan.IsEmpty)])); continue; } @@ -2718,7 +2718,7 @@ newSymbol is IPropertySymbol newProperty && rudeEditKind, diagnosticSpan, oldDeclaration, - new[] { GetDisplayKindAndName(oldSymbol, GetDisplayName(oldDeclaration, EditKind.Delete), fullyQualify: diagnosticSpan.IsEmpty) })); + [GetDisplayKindAndName(oldSymbol, GetDisplayName(oldDeclaration, EditKind.Delete), fullyQualify: diagnosticSpan.IsEmpty)])); continue; } @@ -2853,7 +2853,7 @@ newSymbol is IPropertySymbol newProperty && RudeEditKind.InsertNotSupportedByRuntime, GetDiagnosticSpan(newDeclaration, EditKind.Insert), newDeclaration, - arguments: new[] { GetDisplayName(newDeclaration, EditKind.Insert) })); + arguments: [GetDisplayName(newDeclaration, EditKind.Insert)])); continue; } @@ -2895,7 +2895,7 @@ newSymbol is IPropertySymbol newProperty && RudeEditKind.InsertNotSupportedByRuntime, GetDiagnosticSpan(newDeclaration, EditKind.Insert), newDeclaration, - arguments: new[] { GetDisplayName(newDeclaration, EditKind.Insert) })); + arguments: [GetDisplayName(newDeclaration, EditKind.Insert)])); } oldContainingType = null; @@ -4490,11 +4490,11 @@ private bool ReportCustomAttributeRudeEdits( { if (IsNonCustomAttribute(attributeData)) { - diagnosticContext.Report(RudeEditKind.ChangingNonCustomAttribute, cancellationToken, arguments: new[] - { + diagnosticContext.Report(RudeEditKind.ChangingNonCustomAttribute, cancellationToken, arguments: + [ attributeData.AttributeClass!.Name, GetDisplayKind(diagnosticContext.RequiredNewSymbol) - }); + ]); return false; } @@ -4508,10 +4508,10 @@ private bool ReportCustomAttributeRudeEdits( ContainingNamespace.ContainingNamespace.ContainingNamespace.ContainingNamespace.IsGlobalNamespace: true }) { - diagnosticContext.Report(RudeEditKind.ChangingAttribute, cancellationToken, arguments: new[] - { + diagnosticContext.Report(RudeEditKind.ChangingAttribute, cancellationToken, arguments: + [ attributeData.AttributeClass.Name, - }); + ]); return false; } @@ -4924,11 +4924,11 @@ public void ReportTypeLayoutUpdateRudeEdits(CancellationToken cancellationToken) Report( (newSymbol.ContainingType.TypeKind == TypeKind.Struct) ? RudeEditKind.InsertIntoStruct : RudeEditKind.InsertIntoClassWithLayout, cancellationToken, - arguments: new[] - { + arguments: + [ analyzer.GetDisplayKind(newSymbol), analyzer.GetDisplayKind(newSymbol.ContainingType) - }); + ]); } public DiagnosticContext WithSymbols(ISymbol oldSymbol, ISymbol newSymbol) @@ -5630,7 +5630,7 @@ select clausesByQuery.First()) { if (!CanAddNewLambda(newLambda, newLambdaBody1, newLambdaBody2)) { - diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.InsertNotSupportedByRuntime, GetDiagnosticSpan(newLambda, EditKind.Insert), newLambda, new string[] { GetDisplayName(newLambda, EditKind.Insert) })); + diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.InsertNotSupportedByRuntime, GetDiagnosticSpan(newLambda, EditKind.Insert), newLambda, [GetDisplayName(newLambda, EditKind.Insert)])); } // TODO: https://github.com/dotnet/roslyn/issues/37128 @@ -5638,7 +5638,7 @@ select clausesByQuery.First()) // Although local functions are non-virtual the Core CLR currently does not support adding any method to an interface. if (isInInterface && IsLocalFunction(newLambda)) { - diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.InsertLocalFunctionIntoInterfaceMethod, GetDiagnosticSpan(newLambda, EditKind.Insert), newLambda, new string[] { GetDisplayName(newLambda, EditKind.Insert) })); + diagnostics.Add(new RudeEditDiagnostic(RudeEditKind.InsertLocalFunctionIntoInterfaceMethod, GetDiagnosticSpan(newLambda, EditKind.Insert), newLambda, [GetDisplayName(newLambda, EditKind.Insert)])); } } } @@ -5859,7 +5859,7 @@ private void ReportPrimaryParameterCaptureRudeEdits( RudeEditKind.CapturingPrimaryConstructorParameter, GetSymbolLocationSpan(newCapture, cancellationToken), node: null, - new[] { GetLayoutKindDisplay(newCapture), newCapture.Name })); + [GetLayoutKindDisplay(newCapture), newCapture.Name])); } } @@ -5874,7 +5874,7 @@ private void ReportPrimaryParameterCaptureRudeEdits( RudeEditKind.NotCapturingPrimaryConstructorParameter, GetSymbolLocationSpan(newMember, cancellationToken), node: null, - new[] { GetLayoutKindDisplay(oldCapture), oldCapture.Name })); + [GetLayoutKindDisplay(oldCapture), oldCapture.Name])); } } @@ -6338,7 +6338,7 @@ private static void ReportMissingStateMachineAttribute( // since the attribute has been long defined in the BCL. if (oldCompilation.GetTypeByMetadataName(stateMachineAttributeQualifiedName) == null) { - diagnosticContext.Report(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, cancellationToken, arguments: new[] { stateMachineAttributeQualifiedName }); + diagnosticContext.Report(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, cancellationToken, arguments: [stateMachineAttributeQualifiedName]); } } diff --git a/src/Features/Core/Portable/EditAndContinue/TraceLog.cs b/src/Features/Core/Portable/EditAndContinue/TraceLog.cs index 9284d979721c6..f89486fe9ba13 100644 --- a/src/Features/Core/Portable/EditAndContinue/TraceLog.cs +++ b/src/Features/Core/Portable/EditAndContinue/TraceLog.cs @@ -120,7 +120,7 @@ public void Append(Entry entry) try { path = Path.Combine(_logDirectory, _traceLog._fileName); - File.AppendAllLines(path, new[] { entry.GetDebuggerDisplay() }); + File.AppendAllLines(path, [entry.GetDebuggerDisplay()]); } catch (Exception e) { diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonBraceMatcher.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonBraceMatcher.cs index 5cae292905389..8e9b9e3e92ad6 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonBraceMatcher.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonBraceMatcher.cs @@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.Json.LanguageService ///
[ExportEmbeddedLanguageBraceMatcher( PredefinedEmbeddedLanguageNames.Json, - new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }, + [LanguageNames.CSharp, LanguageNames.VisualBasic], supportsUnannotatedAPIs: true, "Json"), Shared] internal sealed class JsonBraceMatcher : IEmbeddedLanguageBraceMatcher diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonClassifier.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonClassifier.cs index 6bc12323657da..3db64cc628229 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonClassifier.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonClassifier.cs @@ -23,7 +23,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.Json.LanguageService /// [ExportEmbeddedLanguageClassifier( PredefinedEmbeddedLanguageNames.Json, - new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }, + [LanguageNames.CSharp, LanguageNames.VisualBasic], supportsUnannotatedAPIs: true, "Json"), Shared] internal sealed class JsonClassifier : IEmbeddedLanguageClassifier { diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexBraceMatcher.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexBraceMatcher.cs index fdc89b1d4de59..697ceb04c7824 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexBraceMatcher.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexBraceMatcher.cs @@ -24,7 +24,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.L /// [ExportEmbeddedLanguageBraceMatcher( PredefinedEmbeddedLanguageNames.Regex, - new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }, + [LanguageNames.CSharp, LanguageNames.VisualBasic], supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] internal sealed class RegexBraceMatcher : IEmbeddedLanguageBraceMatcher diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexClassifier.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexClassifier.cs index 00c5c0a280d05..f1032a1b6291c 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexClassifier.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexClassifier.cs @@ -25,7 +25,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.L [ExtensionOrder(Before = PredefinedEmbeddedLanguageNames.Json)] [ExportEmbeddedLanguageClassifier( PredefinedEmbeddedLanguageNames.Regex, - new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }, + [LanguageNames.CSharp, LanguageNames.VisualBasic], supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] internal sealed class RegexClassifier : IEmbeddedLanguageClassifier { diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlighter.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlighter.cs index 96ebfe3a952e3..a605c80868105 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlighter.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlighter.cs @@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.L [ExportEmbeddedLanguageDocumentHighlighter( PredefinedEmbeddedLanguageNames.Regex, - new[] { LanguageNames.CSharp, LanguageNames.VisualBasic }, + [LanguageNames.CSharp, LanguageNames.VisualBasic], supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] internal sealed class RegexDocumentHighlighter : IEmbeddedLanguageDocumentHighlighter { diff --git a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/NewUnitTestingIncrementalAnalyzerProvider.cs b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/NewUnitTestingIncrementalAnalyzerProvider.cs index 5f7c354402ad6..f1cf82d3fe09c 100644 --- a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/NewUnitTestingIncrementalAnalyzerProvider.cs +++ b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/NewUnitTestingIncrementalAnalyzerProvider.cs @@ -53,7 +53,7 @@ public void Reanalyze() var metadata = new UnitTestingIncrementalAnalyzerProviderMetadata( analyzerName, - new[] { workspaceKind }); + [workspaceKind]); solutionCrawlerRegistrationService.AddAnalyzerProvider(analyzerProvider, metadata); return analyzerProvider; diff --git a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingIncrementalAnalyzerProvider.cs b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingIncrementalAnalyzerProvider.cs index 4f5c3169e7374..ddb46144c0683 100644 --- a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingIncrementalAnalyzerProvider.cs +++ b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/UnitTestingIncrementalAnalyzerProvider.cs @@ -49,7 +49,7 @@ public void Reanalyze() var metadata = new IncrementalAnalyzerProviderMetadata( analyzerName, highPriorityForActiveFile: false, - new[] { workspace.Kind }); + [workspace.Kind]); solutionCrawlerRegistrationService.AddAnalyzerProvider(analyzerProvider, metadata); return analyzerProvider; diff --git a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs index 40822243071d6..86f5bc1d8330c 100644 --- a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs +++ b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs @@ -411,6 +411,15 @@ private static ImmutableArray CreateInterfaceMembers(IEnumerable CreateInterfaceMembers(IEnumerable ExpandAsync(TSelectionResult selecti var insertionPointAnnotation = new SyntaxAnnotation(); var finalRoot = document.Root.ReplaceSyntax( - nodes: new[] { insertionPointNode }, + nodes: [insertionPointNode], // intentionally using 'n' (new) here. We want to see any updated sub tokens that were updated in computeReplacementToken computeReplacementNode: (o, n) => n.WithAdditionalAnnotations(insertionPointAnnotation), tokens: tokenMap.Keys, diff --git a/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs b/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs index b75d609f5f69d..a8f7dea5f3eef 100644 --- a/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs +++ b/src/Features/Core/Portable/FindUsages/IDefinitionsAndReferencesFactory.cs @@ -151,8 +151,10 @@ private static DefinitionItem ToDefinitionItem( var properties = GetProperties(definition, isPrimary); - if (sourceLocations.IsDefault) + if (sourceLocations.IsDefault || definition.IsTupleType()) { + // If the location is in metadata, then create a metadata definition. + // A special case is the tuple type, where its locations are preserved in the original definition. return DefinitionItem.CreateMetadataDefinition( tags, displayParts, nameDisplayParts, solution, definition, properties, displayIfNoReferences); diff --git a/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs b/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs index f4e259b66ee9c..f6703e724a89a 100644 --- a/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs +++ b/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs @@ -254,7 +254,7 @@ private IMethodSymbol CreateDisposeImplementationMethod( var ifStatement = g.IfStatement( g.LogicalNotExpression(g.IdentifierName(disposedValueField.Name)), - new[] { ifDisposingStatement, disposedValueEqualsTrueStatement }); + [ifDisposingStatement, disposedValueEqualsTrueStatement]); return CodeGenerationSymbolFactory.CreateMethodSymbol( disposeMethod, diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs index b82ef08d07a3e..068bfd81f67e3 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AbstractSymbolDescriptionBuilder.cs @@ -191,15 +191,14 @@ void AddDocumentationPartsWithPrefix(string? rawXmlText, SymbolDescriptionGroups var parts = formatter.Format(rawXmlText, symbol, _semanticModel, _position, format, CancellationToken); if (!parts.IsDefaultOrEmpty) { - using var _ = ArrayBuilder.GetInstance(out var builder); - - builder.Add(new TaggedText(TextTags.Text, prefix)); - builder.AddRange(LineBreak().ToTaggedText()); - builder.Add(new TaggedText(TextTags.ContainerStart, " ")); - builder.AddRange(parts); - builder.Add(new TaggedText(TextTags.ContainerEnd, string.Empty)); - - _documentationMap.Add(group, builder.ToImmutable()); + _documentationMap.Add(group, + [ + new TaggedText(TextTags.Text, prefix), + .. LineBreak().ToTaggedText(), + new TaggedText(TextTags.ContainerStart, " "), + .. parts, + new TaggedText(TextTags.ContainerEnd, string.Empty), + ]); } } } @@ -562,14 +561,14 @@ private async Task> GetFieldPartsAsync(IFieldS var initializerParts = await GetInitializerSourcePartsAsync(symbol).ConfigureAwait(false); if (!initializerParts.IsDefaultOrEmpty) { - using var _ = ArrayBuilder.GetInstance(out var parts); - parts.AddRange(ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat)); - parts.AddRange(Space()); - parts.AddRange(Punctuation("=")); - parts.AddRange(Space()); - parts.AddRange(initializerParts); - - return parts.ToImmutable(); + return + [ + .. ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat), + .. Space(), + .. Punctuation("="), + .. Space(), + .. initializerParts, + ]; } } @@ -594,14 +593,14 @@ private async Task> GetLocalPartsAsync(ILocalS var initializerParts = await GetInitializerSourcePartsAsync(symbol).ConfigureAwait(false); if (initializerParts != null) { - using var _ = ArrayBuilder.GetInstance(out var parts); - parts.AddRange(ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat)); - parts.AddRange(Space()); - parts.AddRange(Punctuation("=")); - parts.AddRange(Space()); - parts.AddRange(initializerParts); - - return parts.ToImmutable(); + return + [ + .. ToMinimalDisplayParts(symbol, MinimallyQualifiedFormat), + .. Space(), + .. Punctuation("="), + .. Space(), + .. initializerParts, + ]; } } diff --git a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs index 9916c6623e42d..b34e772d2fa9a 100644 --- a/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs +++ b/src/Features/Core/Portable/LanguageServices/SymbolDisplayService/AbstractSymbolDisplayService.AnonymousTypes.cs @@ -27,7 +27,7 @@ where part.Symbol.IsAnonymousType() || part.Symbol.IsTupleType() // description. Otherwise, replace it with 'a, 'b etc. and show its sig in the 'Types:' section. if (firstSymbol.IsAnonymousDelegateType()) - directStructuralTypes = directStructuralTypes.Except(new[] { (INamedTypeSymbol)firstSymbol }); + directStructuralTypes = directStructuralTypes.Except([(INamedTypeSymbol)firstSymbol]); var info = LanguageServices.GetRequiredService().GetTypeDisplayInfo( firstSymbol, directStructuralTypes.ToImmutableArrayOrEmpty(), _semanticModel, _position); diff --git a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs index fffcb379a7045..8dcb27016b1e8 100644 --- a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs +++ b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs @@ -121,7 +121,7 @@ private static INamespaceOrTypeSymbol CreateCodeGenerationSymbol(Document docume : CodeGenerationSymbolFactory.CreateNamespaceSymbol( topLevelNamespaceSymbol.ToDisplayString(SymbolDisplayFormats.NameFormat), null, - new[] { wrappedType }); + [wrappedType]); } } } diff --git a/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceFileService.cs b/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceFileService.cs index cbca9d1aa1bbe..90263966542b0 100644 --- a/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceFileService.cs +++ b/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceFileService.cs @@ -305,6 +305,8 @@ private static void TryDeleteFolderWhichContainsReadOnlyFiles(string directoryPa public bool IsNavigableMetadataSymbol(ISymbol symbol) { + symbol = symbol.OriginalDefinition; + if (!symbol.Locations.Any(static l => l.IsInMetadata)) { return false; diff --git a/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceGeneratedFileInfo.cs b/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceGeneratedFileInfo.cs index 2aaaa03bea8bc..339db1b74ad60 100644 --- a/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceGeneratedFileInfo.cs +++ b/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceGeneratedFileInfo.cs @@ -102,7 +102,7 @@ public MetadataAsSourceGeneratedFileInfo(string rootPath, Workspace sourceWorksp checksumAlgorithm: ChecksumAlgorithm), compilationOptions: compilationOptions, parseOptions: _parseOptions, - documents: new[] { assemblyInfoDocument, generatedDocument }, + documents: [assemblyInfoDocument, generatedDocument], metadataReferences: References); return (projectInfo, generatedDocumentId); diff --git a/src/Features/Core/Portable/RQName/Nodes/RQType.cs b/src/Features/Core/Portable/RQName/Nodes/RQType.cs index 3c17a93f59979..07195aea9e7fa 100644 --- a/src/Features/Core/Portable/RQName/Nodes/RQType.cs +++ b/src/Features/Core/Portable/RQName/Nodes/RQType.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Features.RQName.Nodes internal abstract class RQType { public static readonly RQType ObjectType = new RQConstructedType( - new RQUnconstructedType(new[] { "System" }, new[] { new RQUnconstructedTypeInfo("Object", 0) }), + new RQUnconstructedType(["System"], [new RQUnconstructedTypeInfo("Object", 0)]), []); public abstract SimpleTreeNode ToSimpleTree(); diff --git a/src/Features/Core/Portable/ReplaceConditionalWithStatements/AbstractReplaceConditionalWithStatementsCodeRefactoringProvider.cs b/src/Features/Core/Portable/ReplaceConditionalWithStatements/AbstractReplaceConditionalWithStatementsCodeRefactoringProvider.cs index 43bf2e03cb998..4b9ef9e06ac79 100644 --- a/src/Features/Core/Portable/ReplaceConditionalWithStatements/AbstractReplaceConditionalWithStatementsCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ReplaceConditionalWithStatements/AbstractReplaceConditionalWithStatementsCodeRefactoringProvider.cs @@ -250,11 +250,10 @@ private async Task ReplaceConditionalExpressionInLocalDeclarationState var newRoot = root.ReplaceNode( isGlobalStatement ? localDeclarationStatement.GetRequiredParent() : localDeclarationStatement, - new[] - { + [ WrapGlobal(updatedLocalDeclarationStatement), WrapGlobal(ifStatement), - }); + ]); return document.WithSyntaxRoot(newRoot); @@ -290,8 +289,8 @@ private static TStatementSyntax ConvertToIfStatement( return (TStatementSyntax)generator.IfStatement( condition.WithoutTrivia(), - new[] { Rewrite((TExpressionSyntax)whenTrue) }, - new[] { Rewrite((TExpressionSyntax)whenFalse) }); + [Rewrite((TExpressionSyntax)whenTrue)], + [Rewrite((TExpressionSyntax)whenFalse)]); SyntaxNode Rewrite(TExpressionSyntax expression) { diff --git a/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs b/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs index abf6d0a2699ae..f737880364286 100644 --- a/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs +++ b/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs @@ -239,7 +239,7 @@ private static bool IsSafeToRemove(string text) // trivia accordingly. var rewrittenRoot = root.ReplaceSyntax( - nodes: new[] { nodeToFormat }, + nodes: [nodeToFormat], computeReplacementNode: (oldNode, newNode) => newNode.WithAdditionalAnnotations(s_toFormatAnnotation), tokens: leftTokenToTrailingTrivia.Keys.Concat(rightTokenToLeadingTrivia.Keys).Distinct(), diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index eb7c621171092..c6439c02d7061 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -352,12 +352,12 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn
Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + Zachytávání parametru primárního konstruktoru {0}, který se předtím nezachytával, vyžaduje restartování aplikace. Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - Dokončení zachytávání parametru primárního konstruktoru '{0}' '{1}' vyžaduje restartování aplikace. + Dokončení zachytávání parametru primárního konstruktoru{0} z {1} vyžaduje restartování aplikace. @@ -412,7 +412,7 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + Změna atributu {0} vyžaduje restartování aplikace. @@ -607,12 +607,12 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Debug All Tests - Debug All Tests + Ladit všechny testy Debug Test - Debug Test + Ladit test @@ -757,7 +757,7 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Fix All: {0} - Fix All: {0} + Opravit vše: {0} @@ -2517,7 +2517,7 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Remove unnecessary imports or usings - Remove unnecessary imports or usings + Odebrat nepotřebné importy nebo použití @@ -2597,12 +2597,12 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Run All Tests - Run All Tests + Spustit všechny testy Run Test - Run Test + Spustit test @@ -2842,7 +2842,7 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Unwrap collection - Zrušit zalomení kolekce + Zrušit zalomení dlouhé kolekce @@ -3017,7 +3017,7 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Wrap collection - Zalamovat kolekci + Zalomit kolekci @@ -3458,7 +3458,7 @@ Pokud se specifikátor formátu H použije bez dalších specifikátorů vlastn class with explicit or sequential layout - class with explicit or sequential layout + třída s explicitním nebo sekvenčním rozložením diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 40e7722f6e19e..d5f8403a86575 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -352,12 +352,12 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + La capture du paramètre de constructeur principal « {0} » qui n’a pas été capturée avant requiert le redémarrage de l’application. Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - L’annulation de la capture du paramètre de constructeur principal '{0}' de '{1}' nécessite le redémarrage de l’application. + L’annulation de la capture du paramètre de constructeur principal « {0} » de « {1} » nécessite le redémarrage de l’application. @@ -412,7 +412,7 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + La modification de l’attribut « {0} » nécessite le redémarrage de l’application. @@ -527,7 +527,7 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Convert number - Convertir le numéro + Convertir un numéro @@ -607,12 +607,12 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Debug All Tests - Debug All Tests + Déboguer tous les tests Debug Test - Debug Test + Test de débogage @@ -757,7 +757,7 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Fix All: {0} - Fix All: {0} + Corriger tout : {0} @@ -2517,7 +2517,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Remove unnecessary imports or usings - Remove unnecessary imports or usings + Supprimer les utilisations ou les importations inutiles @@ -2597,12 +2597,12 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Run All Tests - Run All Tests + Exécuter tous les tests Run Test - Run Test + Exécuter des tests @@ -2842,7 +2842,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Unwrap collection - Annuler le renvoi à la ligne de la collection + Désenvelopper une collection @@ -3017,7 +3017,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Wrap collection - Envelopper la collection + Envelopper une collection @@ -3052,7 +3052,7 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Wrap long collection - Envelopper la longue collection + Envelopper une longue collection @@ -3458,7 +3458,7 @@ Si le spécificateur de format "H" est utilisé sans autres spécificateurs de f class with explicit or sequential layout - class with explicit or sequential layout + classe avec une disposition séquentielle ou explicite diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 36e831e2e0c56..9cabd1a91d68a 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -307,7 +307,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Awaited task returns {0} - Awaited task returns {0} + 待機中のタスクから {0} が返されました @@ -352,12 +352,12 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + これまでにキャプチャされていないプライマリ コンストラクター パラメーター '{0}' をキャプチャするには、アプリケーションを再起動する必要があります。 Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - '{1}' のプライマリ コンストラクター パラメーター '{0}' をキャプチャするには、アプリケーションを再起動する必要があります。 + '{1}' のプライマリ コンストラクター パラメーター '{0}' のキャプチャを中止するには、アプリケーションを再起動する必要があります。 @@ -412,7 +412,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + 属性 '{0}' を変更するには、アプリケーションを再起動する必要があります。 @@ -607,12 +607,12 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Debug All Tests - Debug All Tests + すべてのテストをデバッグする Debug Test - Debug Test + テストのデバッグ @@ -757,7 +757,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Fix All: {0} - Fix All: {0} + すべて修正: {0} @@ -2517,7 +2517,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Remove unnecessary imports or usings - Remove unnecessary imports or usings + 不要なインポートまたは using の削除 @@ -2597,12 +2597,12 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Run All Tests - Run All Tests + すべてのテストを実行する Run Test - Run Test + テストの実行 @@ -2842,7 +2842,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Unwrap collection - コレクションの折り返しを解除 + コレクションの折り返し解除 @@ -3052,7 +3052,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Wrap long collection - 長いコレクションを折り返す + 長いコレクションの折り返し @@ -3458,7 +3458,7 @@ If the "H" format specifier is used without other custom format specifiers, it's class with explicit or sequential layout - class with explicit or sequential layout + 明示的なレイアウトまたはシーケンシャル レイアウトを持つクラス diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 48f765cb6abc6..8fa8e1a47e203 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -352,12 +352,12 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + Przechwytywanie podstawowego parametru konstruktora „{0}”, który nie został wcześniej przechwycony, wymaga ponownego uruchomienia aplikacji. Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - Próba przechwycenia podstawowego parametru konstruktora '{0}' '{1}' wymaga ponownego uruchomienia aplikacji. + Przerwanie przechwytywania podstawowego parametru konstruktora „{0}” „{1}” wymaga ponownego uruchomienia aplikacji. @@ -412,7 +412,7 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + Zmienianie atrybutu „{0}” wymaga ponownego uruchomienia aplikacji. @@ -607,12 +607,12 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Debug All Tests - Debug All Tests + Debuguj wszystkie testy Debug Test - Debug Test + Debuguj test @@ -757,7 +757,7 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Fix All: {0} - Fix All: {0} + Napraw wszystko: {0} @@ -2517,7 +2517,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Remove unnecessary imports or usings - Remove unnecessary imports or usings + Usuń niepotrzebne importy lub użycia @@ -2597,12 +2597,12 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Run All Tests - Run All Tests + Uruchom wszystkie testy Run Test - Run Test + Wykonaj test @@ -2842,7 +2842,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Unwrap collection - Cofnij zawijanie kolekcji + Odpakuj kolekcję @@ -3017,7 +3017,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Wrap collection - Zawijaj kolekcję + Zwiń kolekcję @@ -3052,7 +3052,7 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Wrap long collection - Zawijaj długą kolekcję + Zwiń długą kolekcję @@ -3458,7 +3458,7 @@ Jeśli specyfikator formatu „H” zostanie użyty bez innych indywidualnych sp class with explicit or sequential layout - class with explicit or sequential layout + klasa z układem jawnie lub sekwencyjnym diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index 29c92e77a708f..e79d5819a63c4 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -352,12 +352,12 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + A captura do parâmetro primário do construtor '{0}' que não tenha sido capturado antes exige a reinicialização do aplicativo. Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. + Deixar de capturar o parâmetro {0} do construtor primário de '{1}' exige a reinicialização do aplicativo. @@ -412,7 +412,7 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + A alteração do atributo '{0}' exige a reinicialização do aplicativo. @@ -607,12 +607,12 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Debug All Tests - Debug All Tests + Depurar Todos os Testes Debug Test - Debug Test + Teste de Depuração @@ -757,7 +757,7 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Fix All: {0} - Fix All: {0} + Corrigir Tudo: {0} @@ -2517,7 +2517,7 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas Remove unnecessary imports or usings - Remove unnecessary imports or usings + Remover Importações ou usos desnecessários @@ -2597,12 +2597,12 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas Run All Tests - Run All Tests + Executar Todos os Testes Run Test - Run Test + Executar o teste @@ -2842,7 +2842,7 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas Unwrap collection - Desencalhar coleção + Desencapsular coleção @@ -3458,7 +3458,7 @@ Se o especificador de formato "H" for usado sem outros especificadores de format class with explicit or sequential layout - class with explicit or sequential layout + classe com layout explícito ou sequencial diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 5acc01c71e860..6bb92c790872c 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -352,12 +352,12 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + Önceden yakalanmamış olan '{0}' birincil oluşturucu parametresini yakalamak için uygulamanın yeniden başlatılmasını gerekir. Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - Birincil oluşturucu parametresinin yakalaması '{0}' '{1}' için uygulamanın yeniden başlatılması gerekir. + '{0}' / '{1}' birincil oluşturucu parametresini yakalama işleminin başlatılması için uygulamanın yeniden başlatılması gerekir. @@ -412,7 +412,7 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + '{0}' özniteliğinin değiştirilmesi için uygulamanın yeniden başlatılması gerekir. @@ -527,7 +527,7 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Convert number - Sladırı dönüştür + Sayıyı dönüştür @@ -607,12 +607,12 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Debug All Tests - Debug All Tests + Tüm Testlerin Hatalarını Ayıkla Debug Test - Debug Test + Testin Hatalarını Ayıkla @@ -757,7 +757,7 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be Fix All: {0} - Fix All: {0} + Tümünü Düzelt: {0} @@ -2517,7 +2517,7 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri Remove unnecessary imports or usings - Remove unnecessary imports or usings + Gereksiz içeri aktarmaları veya kullanmaları kaldır @@ -2597,12 +2597,12 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri Run All Tests - Run All Tests + Tüm Testleri Çalıştır Run Test - Run Test + Testi Çalıştır @@ -3052,7 +3052,7 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri Wrap long collection - Uzun koleksiyonu kaydır + Uzun koleksiyonu sarmala @@ -3458,7 +3458,7 @@ If the "H" format specifier is used without other custom format specifiers, it's class with explicit or sequential layout - class with explicit or sequential layout + açık veya sıralı düzeni olan sınıf diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index c3d106b0aeec5..023a4104d0860 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -352,12 +352,12 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. - Capturing primary constructor parameter '{0}' that hasn't been capture before requires restarting the application. + 擷取之前尚未擷取的主要建構函式參數 '{0}' 需要重新啟動應用程式。 Ceasing to capture primary constructor parameter '{0}' of '{1}' requires restarting the application. - 需要重新開機應用程式,才能擷取 '{1}' 的主要建構函式參數 '{0}'。 + 停止擷取 '{1}' 的主要建構函式參數 '{0}' 需要重新啟動應用程式。 @@ -412,7 +412,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Changing attribute '{0}' requires restarting the application. - Changing attribute '{0}' requires restarting the application. + 變更屬性 '{0}' 需要重新啟動應用程式。 @@ -607,12 +607,12 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Debug All Tests - Debug All Tests + 偵錯所有測試 Debug Test - Debug Test + 偵錯測試 @@ -757,7 +757,7 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Fix All: {0} - Fix All: {0} + 全部修正:{0} @@ -2517,7 +2517,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Remove unnecessary imports or usings - Remove unnecessary imports or usings + 移除不必要的 Import 或 Using @@ -2597,12 +2597,12 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Run All Tests - Run All Tests + 執行所有測試 Run Test - Run Test + 執行測試 @@ -3017,7 +3017,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Wrap collection - 自動換行 + 包裝集合 @@ -3458,7 +3458,7 @@ If the "H" format specifier is used without other custom format specifiers, it's class with explicit or sequential layout - class with explicit or sequential layout + 具有明確或循序配置的類別 diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs index 1f4af0e6605cd..bf38114258d83 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/LanguageServerTestComposition.cs @@ -2,6 +2,9 @@ // 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.Collections.Immutable; +using System.Runtime.Loader; +using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -20,5 +23,17 @@ private static string GetDevKitExtensionPath() => Path.Combine(AppContext.BaseDirectory, DevKitExtensionSubdirectory, DevKitAssemblyFileName); public static Task CreateExportProviderAsync(ILoggerFactory loggerFactory, bool includeDevKitComponents) - => ExportProviderBuilder.CreateExportProviderAsync(extensionAssemblyPaths: [], devKitDependencyPath: includeDevKitComponents ? GetDevKitExtensionPath() : null, loggerFactory: loggerFactory); + { + var devKitDependencyPath = includeDevKitComponents ? GetDevKitExtensionPath() : null; + var serverConfiguration = new ServerConfiguration(LaunchDebugger: false, + MinimumLogLevel: LogLevel.Trace, + StarredCompletionsPath: null, + TelemetryLevel: null, + SessionId: null, + ExtensionAssemblyPaths: [], + DevKitDependencyPath: devKitDependencyPath, + ExtensionLogDirectory: string.Empty); + var extensionAssemblyManager = ExtensionAssemblyManager.Create(serverConfiguration, loggerFactory); + return ExportProviderBuilder.CreateExportProviderAsync(extensionAssemblyManager, devKitDependencyPath, loggerFactory: loggerFactory); + } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/CustomExportAssemblyLoader.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/CustomExportAssemblyLoader.cs index 9fb2d2657b0ea..2ede3fee52f29 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/CustomExportAssemblyLoader.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/CustomExportAssemblyLoader.cs @@ -2,98 +2,95 @@ // 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.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Runtime.Loader; +using Microsoft.CodeAnalysis.LanguageServer.Services; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; namespace Microsoft.CodeAnalysis.LanguageServer; -internal class CustomExportAssemblyLoader : IAssemblyLoader +/// +/// Defines a MEF assembly loader that knows how to load assemblies from both the default assembly load context +/// and from the assembly load contexts for any of our extensions. +/// +internal class CustomExportAssemblyLoader(ExtensionAssemblyManager extensionAssemblyManager, ILoggerFactory loggerFactory) : IAssemblyLoader { - /// - /// Cache assemblies that are already loaded by AssemblyName comparison - /// - private readonly Dictionary _loadedAssemblies = new Dictionary(AssemblyNameComparer.Instance); + private readonly ILogger _logger = loggerFactory.CreateLogger("MEF Assembly Loader"); /// - /// Base directory to search for if initial load fails + /// Loads assemblies from either the host or from our extensions. + /// If an assembly exists in both the host and an extension, we will use the host assembly for the MEF catalog. /// - private readonly string _baseDirectory; + public Assembly LoadAssembly(AssemblyName assemblyName) + { + // VS-MEF generally tries to populate AssemblyName.CodeBase with the path to the assembly being loaded. + // We need to read this in order to figure out which ALC we should load the assembly into. +#pragma warning disable SYSLIB0044 // Type or member is obsolete + var codeBasePath = assemblyName.CodeBase; +#pragma warning restore SYSLIB0044 // Type or member is obsolete + return LoadAssembly(assemblyName, codeBasePath); + } - public CustomExportAssemblyLoader(string baseDirectory) + public Assembly LoadAssembly(string assemblyFullName, string? codeBasePath) { - _baseDirectory = baseDirectory; + var assemblyName = new AssemblyName(assemblyFullName); + return LoadAssembly(assemblyName, codeBasePath); } - public Assembly LoadAssembly(AssemblyName assemblyName) + private Assembly LoadAssembly(AssemblyName assemblyName, string? codeBasePath) { - Assembly? value; - lock (_loadedAssemblies) + _logger.LogTrace($"Loading assembly {assemblyName}"); + // First attempt to load the assembly from the default context. + Exception loadException; + try { - _loadedAssemblies.TryGetValue(assemblyName, out value); + return AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName); } - - if (value == null) + catch (FileNotFoundException ex) { - // Attempt to load the assembly normally, but fall back to Assembly.LoadFrom in the base - // directory if the assembly load fails - try - { - value = Assembly.Load(assemblyName); - } - catch (FileNotFoundException) when (assemblyName.Name is not null) - { - var filePath = Path.Combine(_baseDirectory, assemblyName.Name) - + (assemblyName.Name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) - ? "" - : ".dll"); - - value = Assembly.LoadFrom(filePath); - - if (value is null) - { - throw; - } - } + loadException = ex; + // continue checking the extension contexts. + } - lock (_loadedAssemblies) - { - _loadedAssemblies[assemblyName] = value; - return value; - } + if (codeBasePath is not null) + { + return LoadAssemblyFromCodeBase(assemblyName, codeBasePath); } - return value; - } + // We don't have a code base path for this assembly. We'll look at our map of assembly name + // to extension to see if we can find the assembly in the right context. + var assembly = extensionAssemblyManager.TryLoadAssemblyInExtensionContext(assemblyName); + if (assembly is not null) + { + _logger.LogTrace("{assemblyName} found in extension context without code base", assemblyName); + return assembly; + } - public Assembly LoadAssembly(string assemblyFullName, string? codeBasePath) - { - var assemblyName = new AssemblyName(assemblyFullName); - return LoadAssembly(assemblyName); + _logger.LogCritical("{assemblyName} not found in any host or extension context", assemblyName); + throw loadException; } - private class AssemblyNameComparer : IEqualityComparer + private Assembly LoadAssemblyFromCodeBase(AssemblyName assemblyName, string codeBaseUriStr) { - public static AssemblyNameComparer Instance = new AssemblyNameComparer(); - - public bool Equals(AssemblyName? x, AssemblyName? y) + // CodeBase is spec'd as being a URL string. + var codeBaseUri = ProtocolConversions.CreateAbsoluteUri(codeBaseUriStr); + if (!codeBaseUri.IsFile) { - if (x == null && y == null) - { - return true; - } - - if (x == null || y == null) - { - return false; - } - - return x.Name == y.Name; + throw new ArgumentException($"Code base {codeBaseUriStr} for {assemblyName} is not a file URI.", nameof(codeBaseUriStr)); } - public int GetHashCode([DisallowNull] AssemblyName obj) + var codeBasePath = codeBaseUri.LocalPath; + + var assembly = extensionAssemblyManager.TryLoadAssemblyInExtensionContext(codeBasePath); + if (assembly is not null) { - return obj.Name?.GetHashCode(StringComparison.Ordinal) ?? 0; + _logger.LogTrace("{assemblyName} with code base {codeBase} found in extension context.", assemblyName, codeBasePath); + return assembly; } + + // We were given an explicit code base path, but no extension context had the assembly. + // This is unexpected, so we'll throw an exception. + throw new FileNotFoundException($"Could not find assembly {assemblyName} with code base {codeBasePath} in any extension context."); } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs index a9fc2ee775127..2fd22304a6ddb 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs @@ -4,10 +4,8 @@ using System.Collections.Immutable; using System.Reflection; -using System.Runtime.Loader; using Microsoft.CodeAnalysis.LanguageServer.Logging; using Microsoft.CodeAnalysis.LanguageServer.Services; -using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Composition; @@ -17,14 +15,11 @@ namespace Microsoft.CodeAnalysis.LanguageServer; internal sealed class ExportProviderBuilder { - public static async Task CreateExportProviderAsync(IEnumerable extensionAssemblyPaths, string? devKitDependencyPath, ILoggerFactory loggerFactory) + public static async Task CreateExportProviderAsync(ExtensionAssemblyManager extensionAssemblyManager, string? devKitDependencyPath, ILoggerFactory loggerFactory) { var logger = loggerFactory.CreateLogger(); - var baseDirectory = AppContext.BaseDirectory; - var resolver = new Resolver(new CustomExportAssemblyLoader(baseDirectory)); - // Load any Roslyn assemblies from the extension directory var assemblyPaths = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll"); assemblyPaths = assemblyPaths.Concat(Directory.EnumerateFiles(baseDirectory, "Microsoft.ServiceHub*.dll")); @@ -39,34 +34,29 @@ public static async Task CreateExportProviderAsync(IEnumerable() - { - typeof(ExportProviderBuilder).Assembly - }; - + // DevKit assemblies are not shipped in the main language server folder + // and not included in ExtensionAssemblyPaths (they get loaded into the default ALC). + // So manually add them to the MEF catalog here. if (devKitDependencyPath != null) { - // Load devkit dependencies before other extensions to ensure dependencies - // like VS Telemetry are available from the host. - assemblies.AddRange(LoadDevKitAssemblies(devKitDependencyPath, logger)); + assemblyPaths = assemblyPaths.Concat(devKitDependencyPath); } - foreach (var extensionAssemblyPath in extensionAssemblyPaths) - { - if (AssemblyLoadContextWrapper.TryLoadExtension(extensionAssemblyPath, logger, out var extensionAssembly)) - { - assemblies.Add(extensionAssembly); - } - } + // Add the extension assemblies to the MEF catalog. + assemblyPaths = assemblyPaths.Concat(extensionAssemblyManager.ExtensionAssemblyPaths); + + logger.LogTrace($"Composing MEF catalog using:{Environment.NewLine}{string.Join($" {Environment.NewLine}", assemblyPaths)}."); + + // Create a MEF resolver that can resolve assemblies in the extension contexts. + var resolver = new Resolver(new CustomExportAssemblyLoader(extensionAssemblyManager, loggerFactory)); + + var discovery = PartDiscovery.Combine( + resolver, + new AttributedPartDiscovery(resolver, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) + new AttributedPartDiscoveryV1(resolver)); // TODO - we should likely cache the catalog so we don't have to rebuild it every time. var catalog = ComposableCatalog.Create(resolver) - .AddParts(await discovery.CreatePartsAsync(assemblies)) .AddParts(await discovery.CreatePartsAsync(assemblyPaths)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import @@ -89,25 +79,6 @@ public static async Task CreateExportProviderAsync(IEnumerable LoadDevKitAssemblies(string devKitDependencyPath, ILogger logger) - { - var directoryName = Path.GetDirectoryName(devKitDependencyPath); - Contract.ThrowIfNull(directoryName); - logger.LogTrace("Loading DevKit assemblies from {directory}", directoryName); - - var directory = new DirectoryInfo(directoryName); - using var _ = ArrayBuilder.GetInstance(out var builder); - foreach (var file in directory.GetFiles("*.dll")) - { - logger.LogTrace("Loading {assemblyName}", file.Name); - // DevKit assemblies are loaded into the default load context. This allows extensions - // to share the host's instance of these assemblies as long as they do not ship their own copy. - builder.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName)); - } - - return builder.ToImmutable(); - } - private static void ThrowOnUnexpectedErrors(CompositionConfiguration configuration, ILogger logger) { // Verify that we have exactly the MEF errors that we expect. If we have less or more this needs to be updated to assert the expected behavior. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs index 4d4268f4a1db0..98b8dc984c1d4 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspace.cs @@ -67,7 +67,6 @@ ValueTask ILspWorkspace.UpdateTextIfPresentAsync(DocumentId documentId, SourceTe _ => { this.OnDocumentTextChanged(documentId, sourceText, PreservationMode.PreserveIdentity, requireDocumentPresent: false); - return ValueTask.CompletedTask; }, cancellationToken); } @@ -78,7 +77,6 @@ internal override ValueTask TryOnDocumentOpenedAsync(DocumentId documentId, Sour _ => { this.OnDocumentOpened(documentId, textContainer, isCurrentContext, requireDocumentPresentAndClosed: false); - return ValueTask.CompletedTask; }, cancellationToken); } @@ -86,7 +84,7 @@ internal override ValueTask TryOnDocumentOpenedAsync(DocumentId documentId, Sour internal override ValueTask TryOnDocumentClosedAsync(DocumentId documentId, CancellationToken cancellationToken) { return this.ProjectSystemProjectFactory.ApplyChangeToWorkspaceAsync( - async w => + w => { // TODO(cyrusn): This only works for normal documents currently. We'll have to rethink how things work // in the world if we ever support additionalfiles/editorconfig in our language server. @@ -100,7 +98,9 @@ internal override ValueTask TryOnDocumentClosedAsync(DocumentId documentId, Canc // Dynamic files don't exist on disk so if we were to use the FileTextLoader we'd effectively be emptying out the document. // We also assume they're not user editable, and hence can't have "unsaved" changes that are expected to go away on close. // Instead we just maintain their current state as per the LSP view of the world. - var documentText = await document.GetTextAsync(cancellationToken); + + // Since we know this is a dynamic file, the text is held in memory so GetTextSynchronously is safe to call. + var documentText = document.GetTextSynchronously(cancellationToken); loader = new SourceTextLoader(documentText, filePath); } else diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspaceFactory.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspaceFactory.cs index 29805c51d2a28..3e397764fc809 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspaceFactory.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/LanguageServerWorkspaceFactory.cs @@ -7,8 +7,8 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; using Microsoft.CodeAnalysis.LanguageServer.Handler.DebugConfiguration; +using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.CodeAnalysis.ProjectSystem; using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; using Microsoft.Extensions.Logging; @@ -54,10 +54,10 @@ public LanguageServerWorkspaceFactory( public ProjectSystemHostInfo ProjectSystemHostInfo { get; } public ProjectTargetFrameworkManager TargetFrameworkManager { get; } - public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray analyzerPaths) + public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray analyzerPaths, ExtensionAssemblyManager extensionAssemblyManager) { var references = new List(); - var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader(); + var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader(extensionAssemblyManager, _logger); foreach (var analyzerPath in analyzerPaths) { @@ -75,7 +75,6 @@ public async Task InitializeSolutionLevelAnalyzersAsync(ImmutableArray a await ProjectSystemProjectFactory.ApplyChangeToWorkspaceAsync(w => { w.SetCurrentSolution(s => s.WithAnalyzerReferences(references), WorkspaceChangeKind.SolutionChanged); - return ValueTask.CompletedTask; }); } } diff --git a/src/Features/LanguageServer/Protocol/ExternalAccess/VSCode/API/VSCodeAnalyzerLoader.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/VSCodeAnalyzerLoader.cs similarity index 54% rename from src/Features/LanguageServer/Protocol/ExternalAccess/VSCode/API/VSCodeAnalyzerLoader.cs rename to src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/VSCodeAnalyzerLoader.cs index 4196a791cfd16..e4bdc6f00798c 100644 --- a/src/Features/LanguageServer/Protocol/ExternalAccess/VSCode/API/VSCodeAnalyzerLoader.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/VSCodeAnalyzerLoader.cs @@ -2,14 +2,17 @@ // 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.Collections.Immutable; using System.Composition; +using System.Reflection; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.SolutionCrawler; +using Microsoft.Extensions.Logging; -namespace Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API; +namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; [Export(typeof(VSCodeAnalyzerLoader)), Shared] internal class VSCodeAnalyzerLoader @@ -34,8 +37,33 @@ public void InitializeDiagnosticsServices(Workspace workspace) _diagnosticService.Register((IDiagnosticUpdateSource)_analyzerService); } - public static IAnalyzerAssemblyLoader CreateAnalyzerAssemblyLoader() + public static IAnalyzerAssemblyLoader CreateAnalyzerAssemblyLoader(ExtensionAssemblyManager extensionAssemblyManager, ILogger logger) { - return new DefaultAnalyzerAssemblyLoader(); + return new VSCodeExtensionAssemblyAnalyzerLoader(extensionAssemblyManager, logger); + } + + /// + /// Analyzer loader that will re-use already loaded assemblies from the extension load context. + /// + private class VSCodeExtensionAssemblyAnalyzerLoader(ExtensionAssemblyManager extensionAssemblyManager, ILogger logger) : IAnalyzerAssemblyLoader + { + private readonly DefaultAnalyzerAssemblyLoader _defaultLoader = new(); + + public void AddDependencyLocation(string fullPath) + { + _defaultLoader.AddDependencyLocation(fullPath); + } + + public Assembly LoadFromPath(string fullPath) + { + var assembly = extensionAssemblyManager.TryLoadAssemblyInExtensionContext(fullPath); + if (assembly is not null) + { + logger.LogTrace("Loaded analyzer {fullPath} from extension context", fullPath); + return assembly; + } + + return _defaultLoader.LoadFromPath(fullPath); + } } } diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs index 09c1ab269010e..ef7e08dc3842b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs @@ -7,16 +7,19 @@ using System.Diagnostics; using System.IO.Pipes; using System.Runtime.InteropServices; +using System.Runtime.Loader; using Microsoft.CodeAnalysis.Contracts.Telemetry; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; using Microsoft.CodeAnalysis.LanguageServer.LanguageServer; using Microsoft.CodeAnalysis.LanguageServer.Logging; +using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.CodeAnalysis.LanguageServer.StarredSuggestions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using Newtonsoft.Json; +using Roslyn.Utilities; // Setting the title can fail if the process is run without a window, such // as when launched detached from nodejs @@ -75,8 +78,9 @@ static async Task RunAsync(ServerConfiguration serverConfiguration, Cancellation } logger.LogTrace($".NET Runtime Version: {RuntimeInformation.FrameworkDescription}"); + var extensionManager = ExtensionAssemblyManager.Create(serverConfiguration, loggerFactory); - using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(serverConfiguration.ExtensionAssemblyPaths, serverConfiguration.DevKitDependencyPath, loggerFactory); + using var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync(extensionManager, serverConfiguration.DevKitDependencyPath, loggerFactory); // The log file directory passed to us by VSCode might not exist yet, though its parent directory is guaranteed to exist. Directory.CreateDirectory(serverConfiguration.ExtensionLogDirectory); @@ -96,10 +100,13 @@ static async Task RunAsync(ServerConfiguration serverConfiguration, Cancellation .Select(f => f.FullName) .ToImmutableArray(); - await workspaceFactory.InitializeSolutionLevelAnalyzersAsync(analyzerPaths); + // Include analyzers from extension assemblies. + analyzerPaths = analyzerPaths.AddRange(extensionManager.ExtensionAssemblyPaths); + + await workspaceFactory.InitializeSolutionLevelAnalyzersAsync(analyzerPaths, extensionManager); var serviceBrokerFactory = exportProvider.GetExportedValue(); - StarredCompletionAssemblyHelper.InitializeInstance(serverConfiguration.StarredCompletionsPath, loggerFactory, serviceBrokerFactory); + StarredCompletionAssemblyHelper.InitializeInstance(serverConfiguration.StarredCompletionsPath, extensionManager, loggerFactory, serviceBrokerFactory); // TODO: Remove, the path should match exactly. Workaround for https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1830914. Microsoft.CodeAnalysis.EditAndContinue.EditAndContinueMethodDebugInfoReader.IgnoreCaseWhenComparingDocumentNames = Path.DirectorySeparatorChar == '\\'; diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs deleted file mode 100644 index fa2021ca34f48..0000000000000 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/AssemblyLoadContextWrapper.cs +++ /dev/null @@ -1,131 +0,0 @@ -// 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. - -using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using System.Runtime.Loader; -using Microsoft.Extensions.Logging; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.LanguageServer.Services -{ - internal sealed class AssemblyLoadContextWrapper : IDisposable - { - private AssemblyLoadContext? _assemblyLoadContext; - private readonly ImmutableDictionary _loadedAssemblies; - private readonly ILogger? _logger; - - private AssemblyLoadContextWrapper(AssemblyLoadContext assemblyLoadContext, ImmutableDictionary loadedFiles, ILogger? logger) - { - _assemblyLoadContext = assemblyLoadContext; - _loadedAssemblies = loadedFiles; - _logger = logger; - } - - public static bool TryLoadExtension(string assemblyFilePath, ILogger logger, [NotNullWhen(true)] out Assembly? assembly) - { - var dir = Path.GetDirectoryName(assemblyFilePath); - var fileName = Path.GetFileName(assemblyFilePath); - var fileNameNoExt = Path.GetFileNameWithoutExtension(assemblyFilePath); - - Contract.ThrowIfNull(dir); - Contract.ThrowIfNull(fileName); - Contract.ThrowIfNull(fileNameNoExt); - - var loadContext = TryCreate(fileNameNoExt, dir, logger); - if (loadContext != null) - { - assembly = loadContext.GetAssembly(fileName); - return true; - } - - assembly = null; - return false; - } - - public static AssemblyLoadContextWrapper? TryCreate(string name, string assembliesDirectoryPath, ILogger logger) - { - try - { - logger.LogTrace("[{name}] Loading assemblies in {assembliesDirectoryPath}", name, assembliesDirectoryPath); - - var loadContext = new AssemblyLoadContext(name); - var directory = new DirectoryInfo(assembliesDirectoryPath); - var builder = new Dictionary(); - foreach (var file in directory.GetFiles("*.dll")) - { - logger.LogTrace("[{name}] Loading {assemblyName}", loadContext.Name, file.Name); - builder.Add(file.Name, loadContext.LoadFromAssemblyPath(file.FullName)); - } - - return new AssemblyLoadContextWrapper(loadContext, builder.ToImmutableDictionary(), logger); - } - catch (Exception ex) - { - logger?.LogError(ex, "Failed to initialize AssemblyLoadContext {name}", name); - return null; - } - } - - public Assembly GetAssembly(string name) => _loadedAssemblies[name]; - - public MethodInfo? TryGetMethodInfo(string assemblyName, string className, string methodName) - { - try - { - return GetMethodInfo(assemblyName, className, methodName); - } - catch (Exception ex) - { - _logger?.LogError(ex, "Failed to get method information from {assembly} for {class}.{method}", assemblyName, className, methodName); - return null; - } - } - - public MethodInfo GetMethodInfo(string assemblyName, string className, string methodName) - { - var assembly = GetAssembly(assemblyName); - var completionHelperType = assembly.GetType(className); - if (completionHelperType == null) - { - throw new ArgumentException($"{assembly.FullName} assembly did not contain {className} class"); - } - var createCompletionProviderMethodInto = completionHelperType?.GetMethod(methodName); - if (createCompletionProviderMethodInto == null) - { - throw new ArgumentException($"{className} from {assembly.FullName} assembly did not contain {methodName} method"); - } - return createCompletionProviderMethodInto; - } - - public void Dispose() - { - _assemblyLoadContext?.Unload(); - _assemblyLoadContext = null; - } - - private sealed class AssemblyNameComparer : IEqualityComparer - { - public static readonly AssemblyNameComparer Default = new(); - - public bool Equals(AssemblyName? x, AssemblyName? y) - { - if (ReferenceEquals(x, y)) - return true; - - if (x == null || y == null) - return false; - - return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase) - && string.Equals(x.CultureName, y.CultureName, StringComparison.OrdinalIgnoreCase); - } - - public int GetHashCode(AssemblyName obj) - => HashCode.Combine( - StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Name ?? string.Empty), - StringComparer.OrdinalIgnoreCase.GetHashCode(obj.CultureName ?? string.Empty)); - } - } -} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/ExtensionAssemblyManager.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/ExtensionAssemblyManager.cs new file mode 100644 index 0000000000000..03f3a0ee97477 --- /dev/null +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/ExtensionAssemblyManager.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. + +using System.Collections.Immutable; +using System.Reflection; +using System.Runtime.Loader; +using Microsoft.CodeAnalysis.LanguageServer.StarredSuggestions; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.Extensions.Logging; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.LanguageServer.Services; + +/// +/// Manages extension assembly loading. Extensions are isolated from one another and from the host +/// using assembly load contexts per extension. This allows extensions to: +/// 1. Load their own version of a dependencies by shipping the dependent assembly inside the extension assembly folder. +/// These assemblies will not be visible to the host or other extensions. +/// 2. Load the host version of a dependency by not shipping the dependent assembly in the extension assembly folder. +/// Useful when the extension wants to use state from the assembly setup by the host (e.g. VSTelemetry). +/// +/// The extension load contexts are defined per directory, so if two extension dlls come from the same directory, +/// they will share the same load context. +/// +/// A couple of additional notes: +/// 1. Only the explicitly provided extension assembly paths are loaded into the MEF catalog. If an extension wants +/// to contribute multiple assemblies to the catalog, each assembly must be passed as an extension assembly path. +/// 2. If an extension assembly contains an analyzer, we will re-use the same extension load context to load the analyzer. +/// +internal sealed class ExtensionAssemblyManager +{ + private readonly ImmutableDictionary _directoryLoadContexts; + + private readonly ImmutableDictionary _assemblyFullNameToLoadContext; + + public ImmutableArray ExtensionAssemblyPaths { get; } + + public ExtensionAssemblyManager(ImmutableDictionary directoryLoadContexts, + ImmutableDictionary assemblyFullNameToLoadContext, + ImmutableArray extensionAssemblyPaths) + { + _directoryLoadContexts = directoryLoadContexts; + _assemblyFullNameToLoadContext = assemblyFullNameToLoadContext; + ExtensionAssemblyPaths = extensionAssemblyPaths; + } + + public static ExtensionAssemblyManager Create(ServerConfiguration serverConfiguration, ILoggerFactory loggerFactory) + { + var logger = loggerFactory.CreateLogger(); + if (serverConfiguration.DevKitDependencyPath is not null) + { + // Ensure the Roslyn DevKit assemblies are loaded into the default ALC so that extensions can use them. + ResolveDevKitAssemblies(serverConfiguration.DevKitDependencyPath, loggerFactory); + } + + var directoryLoadContexts = new Dictionary(StringComparer.Ordinal); + var assemblyFullNameToLoadContext = new Dictionary(StringComparer.Ordinal); + using var _ = ArrayBuilder.GetInstance(out var validExtensionAssemblies); + + if (serverConfiguration.StarredCompletionsPath is not null) + { + // HACK: Load the intellicode dll as an extension, but importantly do not add it to the valid extension assemblies set. + // While we do want to load it into its own ALC because it comes from a different ship vehicle, we do not want it + // to contribute to the MEF catalog / analyzers as a 'normal' extension would. Instead it gets reflection loaded elsewhere. + // + // We should migrate the intellicode completion provider to be a normal extension component with MEF provided parts, + // but it requires changes to the intellicode vscode extension and here to access our IServiceBroker instance via MEF. + var starredCompletionsComponentDll = StarredCompletionAssemblyHelper.GetStarredCompletionAssemblyPath(serverConfiguration.StarredCompletionsPath); + Contract.ThrowIfFalse(TryGetOrCreateLoadContext(starredCompletionsComponentDll)); + } + + foreach (var assemblyFilePath in serverConfiguration.ExtensionAssemblyPaths) + { + if (TryGetOrCreateLoadContext(assemblyFilePath)) + { + validExtensionAssemblies.Add(assemblyFilePath); + } + } + + return new ExtensionAssemblyManager(directoryLoadContexts.ToImmutableDictionary(), assemblyFullNameToLoadContext.ToImmutableDictionary(), validExtensionAssemblies.ToImmutable()); + + bool TryGetOrCreateLoadContext(string assemblyFilePath) + { + // Verify that the path is something we can load. + // If it's not, log helpful error messages and no-op. We do not want to take down the server if an extension fails to load. + if (!File.Exists(assemblyFilePath)) + { + logger.LogError("Extension path {assemblyFilePath} does not exist", assemblyFilePath); + return false; + } + + var directory = Path.GetDirectoryName(assemblyFilePath); + if (directory == null) + { + logger.LogError("Failed to get directory from {assemblyFilePath}", assemblyFilePath); + return false; + } + + var assemblyFullName = AssemblyName.GetAssemblyName(assemblyFilePath).FullName; + if (assemblyFullNameToLoadContext.TryGetValue(assemblyFullName, out var existingContext)) + { + // MEF relies on type full names (*without* their assembly names) to identify parts. + // If an extension assembly is added to the catalog twice, then we will almost certainly get duplicate MEF parts + // which breaks consumers who are only expecting one part. + // + // We validate this constraint here by checking for duplicate extension assembly full names. + logger.LogError( + "{assemblyFilePath} with assembly name {assemblyName} conflicts with extension loaded from {existingContextName}", + assemblyFilePath, assemblyFullName, existingContext.Name); + return false; + } + + if (!directoryLoadContexts.TryGetValue(directory, out var directoryContext)) + { + directoryContext = GetOrCreateDirectoryContext(directory, assemblyFilePath); + } + + assemblyFullNameToLoadContext.Add(assemblyFullName, directoryContext); + return true; + } + + AssemblyLoadContext GetOrCreateDirectoryContext(string directory, string assemblyFilePath) + { + if (directoryLoadContexts.TryGetValue(directory, out var directoryContext)) + { + logger.LogTrace("Reusing {contextName} load context for {assemblyFilePath}", directoryContext.Name, assemblyFilePath); + return directoryContext; + } + + // Create an extension assembly load context for the directory that the extension is in. + logger.LogTrace("Creating {contextName} load context for {assemblyFilePath}", directory, assemblyFilePath); + var loadContext = new ExtensionAssemblyLoadContext(directory, loggerFactory); + directoryLoadContexts.Add(directory, loadContext); + return loadContext; + } + } + + private static void ResolveDevKitAssemblies(string devKitDependencyPath, ILoggerFactory loggerFactory) + { + var devKitDependencyDirectory = Path.GetDirectoryName(devKitDependencyPath); + Contract.ThrowIfNull(devKitDependencyDirectory); + var logger = loggerFactory.CreateLogger("DevKitAssemblyResolver"); + + AssemblyLoadContext.Default.Resolving += (context, assemblyName) => + { + var simpleName = assemblyName.Name!; + var assemblyPath = Path.Combine(devKitDependencyDirectory, simpleName + ".dll"); + if (File.Exists(assemblyPath)) + { + logger.LogTrace("Loading {assembly} from DevKit directory", simpleName); + return context.LoadFromAssemblyPath(assemblyPath); + } + + return null; + }; + } + + /// + /// Loads an assembly from an assembly file path into the extension load context for the assembly's directory. + /// If the directory containing the assembly file path is not an extension directory, this will return null. + /// + public Assembly? TryLoadAssemblyInExtensionContext(string assemblyFilePath) + { + var directory = Path.GetDirectoryName(assemblyFilePath); + if (directory == null) + { + return null; + } + + if (_directoryLoadContexts.TryGetValue(directory, out var loadContext)) + { + return loadContext.LoadFromAssemblyPath(assemblyFilePath); + } + + return null; + } + + /// + /// Loads an assembly from an assembly name in the extension load context. + /// This will look for an extension assembly with the same assembly full name. + /// + public Assembly? TryLoadAssemblyInExtensionContext(AssemblyName assemblyName) + { + var assemblyFullName = assemblyName.FullName; + if (_assemblyFullNameToLoadContext.TryGetValue(assemblyFullName, out var loadContext)) + { + return loadContext.LoadFromAssemblyName(assemblyName); + } + + return null; + } + + /// + /// Load context that will search the extension directory for the assembly to load. + /// If the assembly is not found in the extension context it will continue with + /// normal assembly loading to check the host (or potentially other extensions) for the assembly. + /// + private sealed class ExtensionAssemblyLoadContext : AssemblyLoadContext + { + private readonly string _extensionDirectory; + private readonly ILogger _logger; + + public ExtensionAssemblyLoadContext(string extensionDirectory, ILoggerFactory loggerFactory) : base(extensionDirectory) + { + _extensionDirectory = extensionDirectory; + _logger = loggerFactory.CreateLogger($"ALC-{extensionDirectory}"); + } + + protected override Assembly? Load(AssemblyName assemblyName) + { + var simpleName = assemblyName.Name!; + var assemblyPath = Path.Combine(_extensionDirectory, simpleName + ".dll"); + if (File.Exists(assemblyPath)) + { + _logger.LogTrace("Loading {assembly} in this load context", simpleName); + return LoadFromAssemblyPath(assemblyPath); + } + + // This assembly isn't provided by this extension, continue with normal assembly loading + // to check other extensions or the host for this assembly. + _logger.LogTrace("{assembly} not found in this load context", simpleName); + return null; + } + } +} diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs index 70d7aeda9f716..fe5227ad42abe 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Services/StarredCompletions/StarredCompletionsAssemblyHelper.cs @@ -2,12 +2,9 @@ // 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.Diagnostics.CodeAnalysis; using System.Reflection; -using System.Runtime.Loader; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices; -using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices.Services; using Microsoft.CodeAnalysis.LanguageServer.Services; using Microsoft.Extensions.Logging; using Microsoft.ServiceHub.Framework; @@ -17,7 +14,6 @@ namespace Microsoft.CodeAnalysis.LanguageServer.StarredSuggestions; internal static class StarredCompletionAssemblyHelper { private const string CompletionsDllName = "Microsoft.VisualStudio.IntelliCode.CSharp.dll"; - private const string ALCName = "IntelliCode-ALC"; private const string CompletionHelperClassFullName = "PythiaCSDevKit.CSDevKitCompletionHelper"; private const string CreateCompletionProviderMethodName = "CreateCompletionProviderAsync"; @@ -26,6 +22,7 @@ internal static class StarredCompletionAssemblyHelper private static string? s_completionsAssemblyLocation; private static ILogger? s_logger; private static ServiceBrokerFactory? s_serviceBrokerFactory; + private static ExtensionAssemblyManager? s_extensionAssemblyManager; /// /// A gate to guard the actual creation of . This just prevents us from trying to create the provider more than once; once the field is set it @@ -41,7 +38,7 @@ internal static class StarredCompletionAssemblyHelper /// Location of dll for starred completion /// Factory for creating new logger /// Service broker with access to necessary remote services - internal static void InitializeInstance(string? completionsAssemblyLocation, ILoggerFactory loggerFactory, ServiceBrokerFactory serviceBrokerFactory) + internal static void InitializeInstance(string? completionsAssemblyLocation, ExtensionAssemblyManager extensionAssemblyManager, ILoggerFactory loggerFactory, ServiceBrokerFactory serviceBrokerFactory) { // No location provided means it wasn't passed through from C# Dev Kit, so we don't need to initialize anything further if (string.IsNullOrEmpty(completionsAssemblyLocation)) @@ -54,6 +51,12 @@ internal static void InitializeInstance(string? completionsAssemblyLocation, ILo s_completionsAssemblyLocation = completionsAssemblyLocation; s_logger = loggerFactory.CreateLogger(typeof(StarredCompletionAssemblyHelper)); s_serviceBrokerFactory = serviceBrokerFactory; + s_extensionAssemblyManager = extensionAssemblyManager; + } + + internal static string GetStarredCompletionAssemblyPath(string starredCompletionComponentPath) + { + return Path.Combine(starredCompletionComponentPath, CompletionsDllName); } internal static async Task GetCompletionProviderAsync(CancellationToken cancellationToken) @@ -67,8 +70,13 @@ internal static void InitializeInstance(string? completionsAssemblyLocation, ILo return null; // If we were never initialized with any information from Dev Kit, we can't create one - if (s_completionsAssemblyLocation is null || s_logger is null || s_serviceBrokerFactory is null) + if (s_completionsAssemblyLocation is null + || s_logger is null + || s_serviceBrokerFactory is null + || s_extensionAssemblyManager is null) + { return null; + } // If we don't have a connection to a service broker yet, we also can't create one var serviceBroker = s_serviceBrokerFactory.TryGetFullAccessServiceBroker(); @@ -88,14 +96,17 @@ internal static void InitializeInstance(string? completionsAssemblyLocation, ILo try { - var alc = AssemblyLoadContextWrapper.TryCreate(ALCName, s_completionsAssemblyLocation, s_logger); - if (alc is null) + var completionsDllPath = GetStarredCompletionAssemblyPath(s_completionsAssemblyLocation); + s_logger.LogTrace("trying to load intellicode provider"); + var starredCompletionsAssembly = s_extensionAssemblyManager.TryLoadAssemblyInExtensionContext(completionsDllPath); + if (starredCompletionsAssembly is null) { + s_logger.LogTrace("failed to load intellicode provider"); s_previousCreationFailed = true; return null; } - var createCompletionProviderMethodInfo = alc.GetMethodInfo(CompletionsDllName, CompletionHelperClassFullName, CreateCompletionProviderMethodName); + var createCompletionProviderMethodInfo = GetMethodInfo(starredCompletionsAssembly, CompletionHelperClassFullName, CreateCompletionProviderMethodName); s_completionProvider = await CreateCompletionProviderAsync(createCompletionProviderMethodInfo, serviceBroker, s_completionsAssemblyLocation, s_logger); return s_completionProvider; @@ -109,6 +120,21 @@ internal static void InitializeInstance(string? completionsAssemblyLocation, ILo } } + private static MethodInfo GetMethodInfo(Assembly assembly, string className, string methodName) + { + var completionHelperType = assembly.GetType(className); + if (completionHelperType == null) + { + throw new ArgumentException($"{assembly.FullName} assembly did not contain {className} class"); + } + var createCompletionProviderMethodInto = completionHelperType?.GetMethod(methodName); + if (createCompletionProviderMethodInto == null) + { + throw new ArgumentException($"{className} from {assembly.FullName} assembly did not contain {methodName} method"); + } + return createCompletionProviderMethodInto; + } + private static async Task CreateCompletionProviderAsync(MethodInfo createCompletionProviderMethodInfo, IServiceBroker serviceBroker, string modelBasePath, ILogger logger) { var completionProviderObj = createCompletionProviderMethodInfo.Invoke(null, new object[4] { serviceBroker, BrokeredServices.Services.Descriptors.RemoteModelService, modelBasePath, logger }); diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.cs.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.cs.xlf index 2d0482afe8ff8..227b060360053 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.cs.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.cs.xlf @@ -4,32 +4,32 @@ Aborted! - Aborted! + Přerušeno! Attaching debugger to process {0} - Připojuje se ladicí program ke zpracování {0} + Připojování ladicího programu k procesu {0} Building project... - Building project... + Vytváří se sestavení projektu… Canceled! - Canceled! + Zrušeno! Client failed to attach the debugger - Klientovi se nepodařilo připojit ladicí program. + Klientovi se nepodařilo připojit ladicí program Completed (re)load of all projects in {0} - Načtení všech projektů v {0} bylo dokončeno (znovu). + Dokončilo se (opětovné) načtení všech projektů v čase {0} The placeholder is a time duration like 00:15 @@ -39,27 +39,27 @@ Debugging tests... - Debugging tests... + Ladí se testy… Discovering tests... - Discovering tests... + Hledají se testy… Exception thrown while loading {0} - Při načítání {0} se vyvolala výjimka. + Při načítání {0} došlo k výjimce Failed! - Failed! + Nezdařilo se! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - Neúspěšné: {0}, úspěšné: {1}, přeskočené: {2}, celkem: {3}, doba trvání: {4} + Neúspěšné: {0}, Úspěšné: {1}, Přeskočeno: {2}, Celkem: {3}, Doba trvání: {4} @@ -69,17 +69,17 @@ Failed to run restore on {0} - Nepovedlo se spustit obnovení na {0} + Nepovedlo se spustit obnovení u {0} Found {0} tests in {1} - V {1} se našly {0} testy. + Nalezené testy: {0} v {1} Loading {0}... - Loading {0}... + Načítá se {0}… The placeholder is a name of a file @@ -89,17 +89,17 @@ No test methods found in requested range - V požadovaném rozsahu se nenašly žádné testovací metody. + V požadovaném rozsahu se nenašly žádné testovací metody Nothing found to restore - Nenašlo se nic k obnovení. + Nenašlo se nic, co by se dalo obnovit Passed! - Passed! + Úspěch! @@ -109,17 +109,17 @@ Project {0} loaded by C# Dev Kit - Sada C# Dev Kit načetl projekt {0} + Projekt {0} se načetl sadou C# Dev Kit The placeholder is a name of a file Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - Projekty se nepovedlo načíst, protože se nepovedlo najít .NET Framework nástroje sestavení. Zkuste nainstalovat Visual Studio nebo balíček Visual Studio Build Tools nebo podrobnosti najdete v protokolech. + Projekty se nepovedlo načíst, protože se nepovedlo najít nástroje pro sestavení .NET Framework. Zkuste nainstalovat Visual Studio nebo balíček Visual Studio Build Tools, nebo si projděte podrobnosti v protokolech. Projects failed to load because the Mono could not be found. Ensure that Mono and MSBuild are installed, and check the logs for details. - Projekty se nepovedlo načíst, protože se nepovedlo najít Mono. Ujistěte se, že jsou nainstalované Mono a MSBuild, a podrobnosti najdete v protokolech. + Načtení projektů se nezdařilo, protože se nenašel objekt Mono. Ujistěte se, že jsou nainstalované Mono a MSBuild. Podrobnosti najdete v protokolech. @@ -129,27 +129,27 @@ Restore complete - Restore complete + Obnovování se dokončilo Restore started - Restore started + Obnovení bylo zahájeno Restoring {0} - Restoring {0} + Obnovování {0} Running dotnet restore on {0} - Running dotnet restore on {0} + Spouští se dotnet restore u {0} Running tests... - Running tests... + Spouštějí se testy… @@ -169,17 +169,17 @@ Starting test discovery - Starting test discovery + Spouštění zjišťování testů… Starting test run - Spouští se testovací běh. + Spouštění testovacího běhu… Successfully completed load of {0} - Načtení {0} se úspěšně dokončilo. + Načtení {0} se úspěšně dokončilo @@ -189,7 +189,7 @@ Test discovery aborted - Zjišťování testů bylo přerušeno. + Zjišťování testů se přerušilo @@ -199,7 +199,7 @@ There were problems loading project {0}. See log for details. - Při načítání {0} projektu došlo k potížím. Podrobnosti najdete v protokolu. + Při načítání projektu {0} došlo k potížím. Podrobnosti najdete v protokolu. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.fr.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.fr.xlf index 9b6a73f766326..0ac54117c9e63 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.fr.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.fr.xlf @@ -4,7 +4,7 @@ Aborted! - Aborted! + Abandonné ! @@ -14,12 +14,12 @@ Building project... - Building project... + Génération en cours du projet... Canceled! - Canceled! + Annulé ! @@ -29,7 +29,7 @@ Completed (re)load of all projects in {0} - Chargement terminé de tous les projets dans {0} + Chargement ou rechargement terminé de tous les projets dans {0} The placeholder is a time duration like 00:15 @@ -39,12 +39,12 @@ Debugging tests... - Debugging tests... + Débogage en cours des tests... Discovering tests... - Discovering tests... + Découverte de tests en cours… @@ -54,12 +54,12 @@ Failed! - Failed! + Échec ! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - Échec : {0}, Réussite : {1}, Ignoré : {2}, Total : {3}, Durée : {4} + Échec : {0}, Réussi : {1}, Ignoré : {2}, Total : {3}, Durée : {4} @@ -74,12 +74,12 @@ Found {0} tests in {1} - Tests {0} trouvés dans {1} + {0} tests trouvés dans {1} Loading {0}... - Loading {0}... + Chargement en cours de {0}... The placeholder is a name of a file @@ -99,7 +99,7 @@ Passed! - Passed! + Réussi ! @@ -109,17 +109,17 @@ Project {0} loaded by C# Dev Kit - Projet {0} chargé par le kit de développement C# + Projet {0} chargé par le Kit de développement C# The placeholder is a name of a file Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - Échec du chargement des projets, car les outils de génération .NET Framework sont introuvables. Essayez d’installer Visual Studio ou le package Visual Studio Build Tools, ou case activée les journaux pour plus d’informations. + Nous n’avons pas pu charger des projets, car les outils de génération .NET Framework sont introuvables. Essayez d’installer Visual Studio ou le package Visual Studio Build Tools, consultez les journaux pour obtenir plus d’informations. Projects failed to load because the Mono could not be found. Ensure that Mono and MSBuild are installed, and check the logs for details. - Échec du chargement des projets, car le Mono est introuvable. Vérifiez que Mono et MSBuild sont installés et case activée les journaux pour plus d’informations. + Nous n’avons pas pu charger des projets, car le Mono est introuvable. Vérifiez que Mono et MSBuild sont installés et consultez les journaux pour obtenir plus d’informations. @@ -129,27 +129,27 @@ Restore complete - Restore complete + Restauration terminée Restore started - Restore started + La restauration a démarré Restoring {0} - Restoring {0} + Restauration de {0} Running dotnet restore on {0} - Running dotnet restore on {0} + Exécution de dotnet restore sur {0} Running tests... - Running tests... + Exécution en cours des tests... @@ -169,7 +169,7 @@ Starting test discovery - Starting test discovery + Démarrage de la découverte de tests @@ -179,7 +179,7 @@ Successfully completed load of {0} - Chargement de {0} terminé + Chargement correctement terminé de {0} @@ -189,7 +189,7 @@ Test discovery aborted - Test de découverte abandonné + Découverte de tests abandonnée @@ -199,7 +199,7 @@ There were problems loading project {0}. See log for details. - Des problèmes se sont produits lors du chargement des {0} du projet. Pour plus d’informations, consultez le journal. + Des problèmes se sont produits lors du chargement du projet {0}. Pour obtenir plus d’informations, consultez le journal. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.ja.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.ja.xlf index e88af332e0dde..9ab26801ad3ac 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.ja.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.ja.xlf @@ -4,32 +4,32 @@ Aborted! - Aborted! + 中止されました! Attaching debugger to process {0} - デバッガーをプロセス {0} にアタッチしています + プロセス {0} にデバッガーをアタッチしています Building project... - Building project... + プロジェクトをビルドしています... Canceled! - Canceled! + キャンセル済み Client failed to attach the debugger - クライアントはデバッガーをアタッチできませんでした + クライアントがデバッガーをアタッチできませんでした Completed (re)load of all projects in {0} - {0} 内のすべてのプロジェクトの読み込みが完了しました + {0} のすべてのプロジェクトの (再) 読み込みが完了しました The placeholder is a time duration like 00:15 @@ -39,12 +39,12 @@ Debugging tests... - Debugging tests... + テストをデバッグしています... Discovering tests... - Discovering tests... + テストを検出しています... @@ -54,12 +54,12 @@ Failed! - Failed! + 失敗しました! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - 失敗: {0}、成功: {1}、スキップ: {2}、合計: {3}、期間: {4} + 失敗: {0}、合格: {1}、スキップ: {2}、合計: {3}、期間: {4} @@ -74,12 +74,12 @@ Found {0} tests in {1} - {1} で {0} テストが見つかりました + {1} で {0} 件のテストが見つかりました Loading {0}... - Loading {0}... + {0} を読み込んでいます... The placeholder is a name of a file @@ -94,12 +94,12 @@ Nothing found to restore - 復元するものが見つかりません + 復元できるものがありません Passed! - Passed! + 合格しました。 @@ -109,17 +109,17 @@ Project {0} loaded by C# Dev Kit - プロジェクト {0} C# Dev Kit によって読み込まれました + C# Dev Kit によって読み込まれたプロジェクト {0} The placeholder is a name of a file Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - .NET Frameworkビルド ツールが見つからなかったため、プロジェクトを読み込めませんでした。Visual StudioまたはVisual Studio Build Tools パッケージをインストールするか、ログをチェックして詳細を確認してください。 + .NET Framework のビルド ツールが見つからなかったため、プロジェクトを読み込めませんでした。Visual Studio または Visual Studio Build Tools パッケージをインストールするか、ログで詳細を確認してください。 Projects failed to load because the Mono could not be found. Ensure that Mono and MSBuild are installed, and check the logs for details. - Mono が見つからなかったため、プロジェクトを読み込めませんでした。Mono と MSBuild がインストールされていることを確認し、詳細についてはログをチェックしてください。 + Mono が見つからなかったため、プロジェクトを読み込めませんでした。Mono と MSBuild がインストールされていることを確認し、ログで詳細を確認してください。 @@ -129,27 +129,27 @@ Restore complete - Restore complete + 復元が完了しました Restore started - Restore started + 復元が開始されました Restoring {0} - Restoring {0} + {0} を復元しています Running dotnet restore on {0} - Running dotnet restore on {0} + {0} で dotnet restore を実行しています Running tests... - Running tests... + テストを実行しています... @@ -169,12 +169,12 @@ Starting test discovery - Starting test discovery + テストの検出を開始します Starting test run - テストの実行を開始しています + テストの実行を開始します @@ -194,12 +194,12 @@ Test run error: {0} - テストの実行エラー: {0} + テスト実行エラー: {0} There were problems loading project {0}. See log for details. - プロジェクト {0} の読み込み中に問題が発生しました。詳細については、ログを参照してください。 + プロジェクト {0}の読み込み中に問題が発生しました。詳細については、ログを参照してください。 diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pl.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pl.xlf index 6853c58fed65c..b86a4b88f9dcd 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pl.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pl.xlf @@ -4,22 +4,22 @@ Aborted! - Aborted! + Przerwane! Attaching debugger to process {0} - Dołączanie debugera do {0} procesu + Dołączanie debugera do procesu {0} Building project... - Building project... + Kompilowanie projektu... Canceled! - Canceled! + Anulowano! @@ -29,7 +29,7 @@ Completed (re)load of all projects in {0} - Ukończono (ponownie) ładowanie wszystkich projektów w {0} + Ukończono (ponownie)ładowanie wszystkich projektów w usłudze {0} The placeholder is a time duration like 00:15 @@ -39,12 +39,12 @@ Debugging tests... - Debugging tests... + Trwa debugowanie testów... Discovering tests... - Discovering tests... + Wykrywanie testów... @@ -54,12 +54,12 @@ Failed! - Failed! + Zakończone niepowodzeniem! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - Niepowodzenie: {0}, zakończone powodzeniem: {1}, pominięte: {2}, łącznie: {3}, czas trwania: {4} + Niepowodzenie: {0}, zakończone powodzeniem: {1}, pominięte: {2}, łącznie: {3}, czas trwania: {4} @@ -74,12 +74,12 @@ Found {0} tests in {1} - Znaleziono testy {0} w {1} + Znalezione testy ({0}) w {1} Loading {0}... - Loading {0}... + Trwa ładowanie {0}... The placeholder is a name of a file @@ -94,12 +94,12 @@ Nothing found to restore - Nie znaleziono elementów do przywrócenia + Nie znaleziono niczego do przywrócenia Passed! - Passed! + Zakończone powodzeniem! @@ -114,12 +114,12 @@ Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - Nie można załadować projektów, ponieważ nie można odnaleźć .NET Framework narzędzi kompilacji. Spróbuj zainstalować Visual Studio lub pakiet Visual Studio Build Tools albo sprawdź dzienniki, aby uzyskać szczegółowe informacje. + Nie można załadować projektów, ponieważ nie można odnaleźć narzędzi kompilacji platformy .NET Framework. Spróbuj zainstalować program Visual Studio lub pakiet Visual Studio Build Tools albo sprawdź dzienniki, aby uzyskać szczegółowe informacje. Projects failed to load because the Mono could not be found. Ensure that Mono and MSBuild are installed, and check the logs for details. - Nie można załadować projektów, ponieważ nie można odnaleźć narzędzia Mono. Upewnij się, że narzędzia Mono i MSBuild są zainstalowane, i sprawdź dzienniki, aby uzyskać szczegółowe informacje. + Nie można załadować projektów, ponieważ nie można odnaleźć obiektu Mono. Upewnij się, że platformy Mono i MSBuild są zainstalowane, i sprawdź dzienniki, aby uzyskać szczegółowe informacje. @@ -129,27 +129,27 @@ Restore complete - Restore complete + Zakończono przywracanie Restore started - Restore started + Rozpoczęto przywracanie Restoring {0} - Restoring {0} + Przywracanie {0} Running dotnet restore on {0} - Running dotnet restore on {0} + Uruchamianie przywracania dotnet na {0} Running tests... - Running tests... + Trwa wykonywanie testów... @@ -169,17 +169,17 @@ Starting test discovery - Starting test discovery + Uruchamianie odnajdywania testów Starting test run - Rozpoczynanie przebiegu testu + Uruchamianie przebiegu testu Successfully completed load of {0} - Pomyślnie ukończono ładowanie {0} + Pomyślnie ukończono ładowanie elementu {0} @@ -189,7 +189,7 @@ Test discovery aborted - Przerwano odnajdywanie testów + Odnajdywanie testów zostało przerwane @@ -199,7 +199,7 @@ There were problems loading project {0}. See log for details. - Wystąpiły problemy podczas ładowania {0} projektu. Zobacz dziennik, aby uzyskać szczegółowe informacje. + Wystąpiły problemy podczas ładowania projektu {0}. Aby uzyskać szczegółowe informacje, zobacz dziennik. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pt-BR.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pt-BR.xlf index a64a330edb83a..7b4ec7b07678b 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pt-BR.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.pt-BR.xlf @@ -4,62 +4,62 @@ Aborted! - Aborted! + Anulado! Attaching debugger to process {0} - Anexando o depurador para processar {0} + Anexar o depurador ao processo {0} Building project... - Building project... + Compilando o projeto... Canceled! - Canceled! + Cancelado! Client failed to attach the debugger - Falha do cliente ao anexar o depurador + Falha do cliente ao conectar o depurador Completed (re)load of all projects in {0} - Concluído (re)carregamento de todos os projetos em {0} + (Re)carregamento concluído de todos os projetos em {0} The placeholder is a time duration like 00:15 Debugger attached - Depurador anexado + Depurador conectado Debugging tests... - Debugging tests... + Depurando testes... Discovering tests... - Discovering tests... + Detectando os testes... Exception thrown while loading {0} - Exceção lançada ao carregar {0} + Exceção lançada durante o carregamento {0} Failed! - Failed! + Falhou! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - Falha: {0}, Aprovado: {1}, Ignorado: {2}, Total: {3}, Duração: {4} + Falhou: {0}, Passou: {1}, Ignorado: {2}, Total: {3}, Duração: {4} @@ -69,17 +69,17 @@ Failed to run restore on {0} - Falha ao executar a restauração no {0} + Falha ao executar a restauração em {0} Found {0} tests in {1} - Testes {0} encontrados em {1} + Foram encontrados {0} testes em {1} Loading {0}... - Loading {0}... + Carregando {0}... The placeholder is a name of a file @@ -89,7 +89,7 @@ No test methods found in requested range - Nenhum método de teste encontrado no intervalo solicitado + Não foram encontrados métodos de teste no intervalo solicitado @@ -99,7 +99,7 @@ Passed! - Passed! + Passou! @@ -109,17 +109,17 @@ Project {0} loaded by C# Dev Kit - Projeto {0} carregado pelo Kit de Desenvolvimento C# + Projeto {0} carregado pelo C# Dev Kit The placeholder is a name of a file Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - Os projetos não foram carregados porque .NET Framework ferramentas de build não foram encontradas. Tente instalar o Visual Studio ou o pacote Ferramentas de Build do Visual Studio, ou marcar os logs para obter detalhes. + Os projetos não foram carregados porque as ferramentas de compilação do .NET Framework não puderam ser encontradas. Tente instalar o Visual Studio ou o pacote de Ferramentas de Build do Visual Studio, ou verifique os logs para obter detalhes. Projects failed to load because the Mono could not be found. Ensure that Mono and MSBuild are installed, and check the logs for details. - Falha ao carregar os projetos porque o Mono não foi encontrado. Verifique se o Mono e o MSBuild estão instalados e marcar os logs para obter detalhes. + Os projetos não foram carregados porque o Mono não pôde ser encontrado. Certifique-se de que o Mono e o MSBuild estejam instalados e verifique os logs para obter detalhes. @@ -129,27 +129,27 @@ Restore complete - Restore complete + Restauração concluída Restore started - Restore started + Restauração iniciada Restoring {0} - Restoring {0} + Restaurando {0} Running dotnet restore on {0} - Running dotnet restore on {0} + Executando dotnet restore em {0} Running tests... - Running tests... + Executando os testes... @@ -159,7 +159,7 @@ Show C# logs - Mostrar logs C# + Mostrar logs de C# @@ -169,17 +169,17 @@ Starting test discovery - Starting test discovery + Iniciando a detecção de testes Starting test run - Iniciando execução de teste + Iniciando a execução de teste Successfully completed load of {0} - Carregamento de {0} + Carregamento de {0} concluído com sucesso @@ -189,7 +189,7 @@ Test discovery aborted - Descoberta de teste anulada + Detecção de teste abortada diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.tr.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.tr.xlf index b62987ff0d03c..8b0e80adeff26 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.tr.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.tr.xlf @@ -4,32 +4,32 @@ Aborted! - Aborted! + Durduruldu! Attaching debugger to process {0} - Hata ayıklayıcısı işlemeye {0} + Hata ayıklayıcı, {0} işlemine ekleniyor Building project... - Building project... + Proje derleniyor… Canceled! - Canceled! + İptal edildi! Client failed to attach the debugger - İstemci hata ayıklayıcıyı ekleyemedi + İstemci, hata ayıklayıcıyı ekleyemedi Completed (re)load of all projects in {0} - Projedeki tüm projelerin yüklemesi tamamlandı (yeniden {0} + Tüm projelerin (yeniden) yüklemesi {0} içinde tamamlandı The placeholder is a time duration like 00:15 @@ -39,27 +39,27 @@ Debugging tests... - Debugging tests... + Test hataları ayıklanıyor... Discovering tests... - Discovering tests... + Testler bulunuyor... Exception thrown while loading {0} - Yükleme sırasında özel durum {0} + {0} yüklemesi sırasında özel durum oluştu Failed! - Failed! + Başarısız! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - Başarısız: {0}, Başarılı: {1}, Atlandı: {2}, Toplam: {3}, Süre: {4} + Başarısız: {0}, Başarılı: {1}, Atlandı: {2}, Toplam: {3}, Süre: {4} @@ -69,17 +69,17 @@ Failed to run restore on {0} - Geri yükleme şu sunucuda çalıştırılamadı{0} + Geri yükleme {0} öğesinde çalıştırılamadı Found {0} tests in {1} - Bu {0} testler {1} + {1} içinde {0} test bulundu Loading {0}... - Loading {0}... + {0} yükleniyor... The placeholder is a name of a file @@ -99,7 +99,7 @@ Passed! - Passed! + Başarılı! @@ -109,12 +109,12 @@ Project {0} loaded by C# Dev Kit - Proje {0} C# Geliştirme Seti tarafından yüklendi + {0} Projesi, C# Geliştirme Seti tarafından yüklendi The placeholder is a name of a file Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - Derleme araçları bulunamadığından .NET Framework projeler yüklenemedi. Bu paketi Visual Studio pakete Visual Studio Derleme Araçları deneyin veya ayrıntılar için günlüklere bakın. + .NET Framework derleme araçları bulunamadığından projeler yüklenemedi. Visual Studio veya Visual Studio Derleme Araçları paketini yüklemeyi deneyin veya ayrıntılar için günlüklere bakın. @@ -129,27 +129,27 @@ Restore complete - Restore complete + Geri yükleme tamamlandı Restore started - Restore started + Geri yükleme başlatıldı Restoring {0} - Restoring {0} + {0} geri yükleniyor Running dotnet restore on {0} - Running dotnet restore on {0} + dotnet restore, {0} üzerinde çalıştırılıyor Running tests... - Running tests... + Testler çalıştırılıyor... @@ -169,7 +169,7 @@ Starting test discovery - Starting test discovery + Test bulma başlatılıyor @@ -179,7 +179,7 @@ Successfully completed load of {0} - Dosya yüklemesi başarıyla {0} + {0} yüklemesi başarıyla tamamlandı @@ -199,7 +199,7 @@ There were problems loading project {0}. See log for details. - Proje ayarları yüklenirken sorun {0}. Ayrıntılar için günlüğe bakın. + {0} projesi yüklenirken sorun oluştu. Ayrıntılar için günlüğe bakın. diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.zh-Hant.xlf b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.zh-Hant.xlf index 845bee15d326b..28a62b689ff64 100644 --- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.zh-Hant.xlf +++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/xlf/LanguageServerResources.zh-Hant.xlf @@ -4,62 +4,62 @@ Aborted! - Aborted! + 已中止! Attaching debugger to process {0} - 正在將偵錯工具連結到處理程式 {0} + 正在將偵錯工具連結到處理序 {0} Building project... - Building project... + 正在建置專案... Canceled! - Canceled! + 已取消! Client failed to attach the debugger - 用戶端無法附加偵錯工具 + 用戶端無法連結偵錯工具 Completed (re)load of all projects in {0} - 已完成 (重新){0} 中所有專案的負載 + 已完成 {0} 中所有專案的(重新)載入 The placeholder is a time duration like 00:15 Debugger attached - 已附加偵錯工具 + 已連結偵錯工具 Debugging tests... - Debugging tests... + 正在偵錯測試... Discovering tests... - Discovering tests... + 正在探索測試... Exception thrown while loading {0} - 載入 {0} 時發生例外狀況 + 載入 {0} 時擲回例外狀況 Failed! - Failed! + 失敗! Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} - Failed: {0}, Passed: {1}, Skipped: {2}, Total: {3}, Duration: {4} + 失敗: {0},通過: {1},跳過: {2},總計: {3},持續時間: {4} @@ -74,12 +74,12 @@ Found {0} tests in {1} - 在 {1} 中找到 {0} 測試 + 在 {1} 中找到 {0} 個測試 Loading {0}... - Loading {0}... + 正在載入 {0}... The placeholder is a name of a file @@ -94,12 +94,12 @@ Nothing found to restore - 找不到可還原的專案 + 找不到可還原的項目 Passed! - Passed! + 通過! @@ -109,17 +109,17 @@ Project {0} loaded by C# Dev Kit - 專案 {0} 由 C# 開發工具組載入 + 由 C# 開發人員套件載入的專案 {0} The placeholder is a name of a file Projects failed to load because the .NET Framework build tools could not be found. Try installing Visual Studio or the Visual Studio Build Tools package, or check the logs for details. - 無法載入專案,因為找不到.NET Framework建置工具。請嘗試安裝Visual Studio或Visual Studio Build Tools套件,或查看記錄檔以取得詳細資料。 + 無法載入專案,因為找不到.NET Framework 建置工具。請嘗試安裝 Visual Studio 或 Visual Studio Build Tools 套件,或查看記錄以尋求詳細資料。 Projects failed to load because the Mono could not be found. Ensure that Mono and MSBuild are installed, and check the logs for details. - 無法載入專案,因為找不到 Mono。請確認已安裝 Mono 和 MSBuild,並查看記錄檔以取得詳細資料。 + 無法載入專案,因為找不到 Mono。請確認已安裝 Mono 和 MSBuild,並查看記錄以尋求詳細資料。 @@ -129,27 +129,27 @@ Restore complete - Restore complete + 還原完成 Restore started - Restore started + 還原已開始 Restoring {0} - Restoring {0} + 正在還原 {0} Running dotnet restore on {0} - Running dotnet restore on {0} + 正在 {0} 上執行 dotnet restore Running tests... - Running tests... + 正在執行測試... @@ -169,17 +169,17 @@ Starting test discovery - Starting test discovery + 即將開始測試探索 Starting test run - 正在開始測試回合 + 即將開始測試回合 Successfully completed load of {0} - 已成功完成載入 {0} + 已成功完成 {0} 的載入 @@ -194,12 +194,12 @@ Test run error: {0} - Test run error: {0} + 測試回合錯誤:{0} There were problems loading project {0}. See log for details. - 載入專案 {0} 時發生問題。如需詳細資料,請參閱記錄檔。 + 載入專案 {0} 時發生問題。查看記錄以尋求詳細資料。 diff --git a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs index e082cb6476f59..890759ebb9ceb 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs @@ -54,13 +54,7 @@ public static Uri CreateUriForDocumentWithoutFilePath(this TextDocument document var projectDirectoryName = Path.GetDirectoryName(document.Project.FilePath); Contract.ThrowIfNull(projectDirectoryName); - - using var _ = ArrayBuilder.GetInstance(capacity: 2 + document.Folders.Count, out var pathBuilder); - pathBuilder.Add(projectDirectoryName); - pathBuilder.AddRange(document.Folders); - pathBuilder.Add(document.Name); - - var path = Path.Combine(pathBuilder.ToArray()); + var path = Path.Combine([projectDirectoryName, .. document.Folders, document.Name]); return ProtocolConversions.CreateAbsoluteUri(path); } diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs index 52f26173d6bcb..6d7750cd564bf 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics { [ExportIncrementalAnalyzerProvider( highPriorityForActiveFile: true, name: WellKnownSolutionCrawlerAnalyzers.Diagnostic, - workspaceKinds: new string[] { WorkspaceKind.Host, WorkspaceKind.Interactive })] + workspaceKinds: [WorkspaceKind.Host, WorkspaceKind.Interactive])] internal partial class DiagnosticAnalyzerService : IIncrementalAnalyzerProvider { public IIncrementalAnalyzer CreateIncrementalAnalyzer(Workspace workspace) diff --git a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs index b64816e11b9cb..f525f1f1a0602 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs @@ -12,7 +12,7 @@ internal static class WorkspaceConfigurationOptionsStorage { public static WorkspaceConfigurationOptions GetWorkspaceConfigurationOptions(this IGlobalOptionService globalOptions) => new( - CacheStorage: globalOptions.GetOption(CloudCacheFeatureFlag) ? StorageDatabase.CloudCache : globalOptions.GetOption(Database), + CacheStorage: globalOptions.GetOption(Database), EnableOpeningSourceGeneratedFiles: globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspace) ?? globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag), DisableRecoverableText: globalOptions.GetOption(DisableRecoverableText), @@ -22,9 +22,6 @@ public static WorkspaceConfigurationOptions GetWorkspaceConfigurationOptions(thi public static readonly Option2 Database = new( "dotnet_storage_database", WorkspaceConfigurationOptions.Default.CacheStorage, serializer: EditorConfigValueSerializer.CreateSerializerForEnum()); - public static readonly Option2 CloudCacheFeatureFlag = new( - "dotnet_storage_cloud_cache", WorkspaceConfigurationOptions.Default.CacheStorage == StorageDatabase.CloudCache); - public static readonly Option2 DisableRecoverableText = new( "dotnet_disable_recoverable_text", WorkspaceConfigurationOptions.Default.DisableRecoverableText); diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs index 2be41f522f7b8..d7d1e0d2a920b 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/DocumentPullDiagnosticHandler.cs @@ -32,8 +32,7 @@ public DocumentPullDiagnosticHandler( => diagnosticsParams.TextDocument; protected override VSInternalDiagnosticReport[] CreateReport(TextDocumentIdentifier identifier, Roslyn.LanguageServer.Protocol.Diagnostic[]? diagnostics, string? resultId) - => new[] - { + => [ new VSInternalDiagnosticReport { Diagnostics = diagnostics, @@ -45,7 +44,7 @@ protected override VSInternalDiagnosticReport[] CreateReport(TextDocumentIdentif // values which are cached and may be out of date. Supersedes = WorkspaceDiagnosticIdentifier, } - }; + ]; protected override VSInternalDiagnosticReport[] CreateRemovedReport(TextDocumentIdentifier identifier) => CreateReport(identifier, diagnostics: null, resultId: null); diff --git a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs index 598eedc08620f..f519b0a632cbd 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Diagnostics/WorkspacePullDiagnosticHandler.cs @@ -25,7 +25,7 @@ internal sealed partial class WorkspacePullDiagnosticHandler( => diagnosticsParams.QueryingDiagnosticKind?.Value; protected override VSInternalWorkspaceDiagnosticReport[] CreateReport(TextDocumentIdentifier identifier, Roslyn.LanguageServer.Protocol.Diagnostic[]? diagnostics, string? resultId) - => new[] { + => [ new VSInternalWorkspaceDiagnosticReport { TextDocument = identifier, @@ -35,7 +35,7 @@ protected override VSInternalWorkspaceDiagnosticReport[] CreateReport(TextDocume // same file produced by the DocumentPullDiagnosticHandler. Identifier = WorkspaceDiagnosticIdentifier, } - }; + ]; protected override VSInternalWorkspaceDiagnosticReport[] CreateRemovedReport(TextDocumentIdentifier identifier) => CreateReport(identifier, diagnostics: null, resultId: null); diff --git a/src/Features/LanguageServer/Protocol/Protocol/CodeActionOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/CodeActionOptions.cs index 698727c5466cc..3b32c4f3ec6bf 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/CodeActionOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/CodeActionOptions.cs @@ -35,11 +35,7 @@ public CodeActionKind[]? CodeActionKinds /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } /// /// Gets or sets a value indicating whether the server provides support to resolve diff --git a/src/Features/LanguageServer/Protocol/Protocol/CodeLensOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/CodeLensOptions.cs index 23cd60deaf41b..eddb78e41bf39 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/CodeLensOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/CodeLensOptions.cs @@ -31,10 +31,6 @@ public bool ResolveProvider /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/CompletionOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/CompletionOptions.cs index 2671ce6ef6959..95c31bb7af59b 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/CompletionOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/CompletionOptions.cs @@ -53,11 +53,7 @@ public bool ResolveProvider /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } /// /// Gets or sets completion item setting. diff --git a/src/Features/LanguageServer/Protocol/Protocol/Converters/StringEnumConverter.cs b/src/Features/LanguageServer/Protocol/Protocol/Converters/StringEnumConverter.cs index 2e93f97371f87..64d2ae3d53d6e 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Converters/StringEnumConverter.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Converters/StringEnumConverter.cs @@ -25,7 +25,7 @@ internal class StringEnumConverter static StringEnumConverter() { // TODO. When C# starts supporting static methods in interfaces, add a static Create method to IStringEnum and remove CreateEnum. - var constructor = typeof(TStringEnumType).GetConstructor(new Type[] { typeof(string) }); + var constructor = typeof(TStringEnumType).GetConstructor([typeof(string)]); if (constructor is null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, LanguageServerProtocolResources.StringEnumMissingConstructor, typeof(TStringEnumType).FullName)); diff --git a/src/Features/LanguageServer/Protocol/Protocol/Converters/SumConverter.cs b/src/Features/LanguageServer/Protocol/Protocol/Converters/SumConverter.cs index 1ef563f3ff4d6..60665041fd710 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Converters/SumConverter.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Converters/SumConverter.cs @@ -87,7 +87,7 @@ public override bool CanConvert(Type objectType) sumValue = token.ToObject(unionTypeInfo.Type, serializer); } - object?[] args = { sumValue }; + object?[] args = [sumValue]; var sum = unionTypeInfo.Constructor.Invoke(args); return sum; } @@ -186,7 +186,7 @@ public SumTypeInfoCache(Type sumTypeType) foreach (var parameterType in parameterTypes) { var parameterTypeInfo = NormalizeToNonNullable(parameterType).GetTypeInfo(); - var declaredConstructor = typeInfo.GetConstructor(new Type[] { parameterType }) ?? + var declaredConstructor = typeInfo.GetConstructor([parameterType]) ?? throw new ArgumentException(nameof(sumTypeType), "All constructor parameter types must be represented in the generic type arguments of the SumType"); var kindAttribute = parameterType.GetCustomAttribute(); diff --git a/src/Features/LanguageServer/Protocol/Protocol/DefinitionOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DefinitionOptions.cs index 10493fb0aa1cc..2469f7a97db8e 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DefinitionOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DefinitionOptions.cs @@ -20,10 +20,6 @@ internal class DefinitionOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/DiagnosticOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DiagnosticOptions.cs index e9b7898c56d37..e464c6eb9a8a8 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DiagnosticOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DiagnosticOptions.cs @@ -20,11 +20,7 @@ internal class DiagnosticOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } /// /// Gets or sets the identifier in which the diagnostics are bucketed by the client. diff --git a/src/Features/LanguageServer/Protocol/Protocol/DocumentColorOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DocumentColorOptions.cs index c3c1097998f71..dbad3759bf15b 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DocumentColorOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DocumentColorOptions.cs @@ -20,10 +20,6 @@ internal class DocumentColorOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/DocumentFormattingOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DocumentFormattingOptions.cs index 6428db78e15a3..24f1e6f2008e9 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DocumentFormattingOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DocumentFormattingOptions.cs @@ -20,10 +20,6 @@ internal class DocumentFormattingOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/DocumentHighlightOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DocumentHighlightOptions.cs index a964e6d79e7fe..40333c450d29b 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DocumentHighlightOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DocumentHighlightOptions.cs @@ -20,10 +20,6 @@ internal class DocumentHighlightOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/DocumentLinkOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DocumentLinkOptions.cs index f2334f4ffe47a..42625d49b51a9 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DocumentLinkOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DocumentLinkOptions.cs @@ -31,10 +31,6 @@ public bool ResolveProvider /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/DocumentRangeFormattingOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DocumentRangeFormattingOptions.cs index 29f53cf25852f..8dc450883122a 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DocumentRangeFormattingOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DocumentRangeFormattingOptions.cs @@ -20,10 +20,6 @@ internal class DocumentRangeFormattingOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/DocumentSymbolOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/DocumentSymbolOptions.cs index d12b5f9552b1e..2ea84c8ca9ca6 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/DocumentSymbolOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/DocumentSymbolOptions.cs @@ -20,10 +20,6 @@ internal class DocumentSymbolOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/ExecuteCommandOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/ExecuteCommandOptions.cs index ef7afc7431db0..6cdae0d11cafc 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/ExecuteCommandOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/ExecuteCommandOptions.cs @@ -30,10 +30,6 @@ public string[] Commands /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSDiagnosticTags.cs b/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSDiagnosticTags.cs index a5a54652689ff..c79d5b5ef2aa3 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSDiagnosticTags.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSDiagnosticTags.cs @@ -12,12 +12,12 @@ internal static class VSDiagnosticTags /// /// A entry generated by the build. /// - public const DiagnosticTag BuildError = (DiagnosticTag)(-1); + public const DiagnosticTag BuildError = (DiagnosticTag)(int.MaxValue - 1); /// /// A entry generated by Intellisense. /// - public const DiagnosticTag IntellisenseError = (DiagnosticTag)(-2); + public const DiagnosticTag IntellisenseError = (DiagnosticTag)(int.MaxValue - 2); /// /// A entry that could be generated from both builds @@ -27,37 +27,37 @@ internal static class VSDiagnosticTags /// in the error list if the error list is displaying build and intellisense /// errors. /// - public const DiagnosticTag PotentialDuplicate = (DiagnosticTag)(-3); + public const DiagnosticTag PotentialDuplicate = (DiagnosticTag)(int.MaxValue - 3); /// /// A entry is never displayed in the error list. /// - public const DiagnosticTag HiddenInErrorList = (DiagnosticTag)(-4); + public const DiagnosticTag HiddenInErrorList = (DiagnosticTag)(int.MaxValue - 4); /// /// The entry is always displayed in the error list. /// - public const DiagnosticTag VisibleInErrorList = (DiagnosticTag)(-5); + public const DiagnosticTag VisibleInErrorList = (DiagnosticTag)(int.MaxValue - 5); /// /// The entry is never displayed in the editor. /// - public const DiagnosticTag HiddenInEditor = (DiagnosticTag)(-6); + public const DiagnosticTag HiddenInEditor = (DiagnosticTag)(int.MaxValue - 6); /// /// No tooltip is shown for the entry in the editor. /// - public const DiagnosticTag SuppressEditorToolTip = (DiagnosticTag)(-7); + public const DiagnosticTag SuppressEditorToolTip = (DiagnosticTag)(int.MaxValue - 7); /// /// The entry is represented in the Editor as an Edit /// and Continue error. /// - public const DiagnosticTag EditAndContinueError = (DiagnosticTag)(-8); + public const DiagnosticTag EditAndContinueError = (DiagnosticTag)(int.MaxValue - 8); /// /// A entry is represented in the Editor as a Task List item in the TODO list. /// - public const DiagnosticTag TaskItem = (DiagnosticTag)(-9); + public const DiagnosticTag TaskItem = (DiagnosticTag)(int.MaxValue - 9); } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSServerCapabilities.cs b/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSServerCapabilities.cs index 6985e61b5ba06..3cd00971b4a28 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSServerCapabilities.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Extensions/VSServerCapabilities.cs @@ -26,4 +26,4 @@ public bool ProjectContextProvider set; } } -} \ No newline at end of file +} diff --git a/src/Features/LanguageServer/Protocol/Protocol/FoldingRangeOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/FoldingRangeOptions.cs index 61b531332810d..c68fcaaa0a074 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/FoldingRangeOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/FoldingRangeOptions.cs @@ -20,10 +20,6 @@ internal class FoldingRangeOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/HoverOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/HoverOptions.cs index a34a473e58952..0d5001c8105d4 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/HoverOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/HoverOptions.cs @@ -20,10 +20,6 @@ internal class HoverOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/IWorkDoneProgressOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/IWorkDoneProgressOptions.cs index d522a0fd552ef..5ed79725eacb1 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/IWorkDoneProgressOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/IWorkDoneProgressOptions.cs @@ -14,10 +14,6 @@ internal interface IWorkDoneProgressOptions /// /// See the Language Server Protocol specification for additional information. /// - bool WorkDoneProgress - { - get; - set; - } + bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/ImplementationOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/ImplementationOptions.cs index e158e93bd7b75..8a4cc0363a9bd 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/ImplementationOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/ImplementationOptions.cs @@ -20,10 +20,6 @@ internal class ImplementationOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/InlayHintOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/InlayHintOptions.cs index 28b384ae81ee0..b86910b8786b0 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/InlayHintOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/InlayHintOptions.cs @@ -20,11 +20,7 @@ internal class InlayHintOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } /// /// Gets or sets a value indicating whether or not the inlay hints support has a resolve provider. diff --git a/src/Features/LanguageServer/Protocol/Protocol/Internal/Diagnostics/VSInternalDiagnosticOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/Internal/Diagnostics/VSInternalDiagnosticOptions.cs index 39c5a27db93a1..5ae9280872f06 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Internal/Diagnostics/VSInternalDiagnosticOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Internal/Diagnostics/VSInternalDiagnosticOptions.cs @@ -11,7 +11,7 @@ namespace Roslyn.LanguageServer.Protocol /// Server provided options for pull diagnostic requests. /// [DataContract] - internal class VSInternalDiagnosticOptions : IWorkDoneProgressOptions + internal record class VSInternalDiagnosticOptions : IWorkDoneProgressOptions { /// /// Gets or sets a list of id's used to identify diagnostics that may be coming @@ -22,32 +22,27 @@ internal class VSInternalDiagnosticOptions : IWorkDoneProgressOptions /// [DataMember(Name = "_vs_buildOnlyDiagnosticIds")] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string[]? BuildOnlyDiagnosticIds - { - get; - set; - } + public string[]? BuildOnlyDiagnosticIds { get; init; } /// /// Gets or sets a list of diagnostic kinds used to query diagnostics in each context. /// [DataMember(Name = "_vs_diagnosticKinds")] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public VSInternalDiagnosticKind[]? DiagnosticKinds - { - get; - set; - } + public VSInternalDiagnosticKind[]? DiagnosticKinds { get; init; } + + /// + /// Gets or sets a value indicating whether the server provides support for sending diagnostics requests for all project contexts. + /// + [DataMember(Name = "_vs_supportsMultipleContextDiagnostics")] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public bool SupportsMultipleContextsDiagnostics { get; init; } /// /// Gets or sets a value indicating whether work done progress is supported. /// [DataMember(Name = "_vs_workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKindModifiers.cs b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKindModifiers.cs index 336ebbd50976e..db9c6efd3ba04 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKindModifiers.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKindModifiers.cs @@ -59,8 +59,8 @@ internal static class VSInternalKnownKindModifiers /// /// Collection of known response kind modifier strings. /// - public static readonly IReadOnlyCollection AllModifiers = new[] - { + public static readonly IReadOnlyCollection AllModifiers = + [ Public, Private, Protected, @@ -70,6 +70,6 @@ internal static class VSInternalKnownKindModifiers Snippet, Friend, Declaration, - }; + ]; } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKinds.cs b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKinds.cs index 8e629a148331b..57c78cf29ba71 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKinds.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalKnownKinds.cs @@ -219,8 +219,8 @@ internal static class VSInternalKnownKinds /// /// Collection of response kind strings. /// - public static readonly IReadOnlyCollection AllKinds = new[] - { + public static readonly IReadOnlyCollection AllKinds = + [ Text, Method, Function, @@ -262,6 +262,6 @@ internal static class VSInternalKnownKinds Delegate, Tag, Attribute, - }; + ]; } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalMultipleContextFeatures.cs b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalMultipleContextFeatures.cs deleted file mode 100644 index 54b2578b76c25..0000000000000 --- a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalMultipleContextFeatures.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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 Roslyn.LanguageServer.Protocol -{ - using System.Runtime.Serialization; - using Newtonsoft.Json; - - /// - /// Lists the features that support sending off feature requests for all available project contexts instead of the default active one. - /// - [DataContract] - internal class VSInternalMultipleContextFeatures - { - /// - /// Gets or sets a value indicating whether the server provides support for sending diagnostics requests for all project contexts. - /// - [DataMember(Name = "_vs_SupportsMultipleContextDiagnostics")] - [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool SupportsMultipleContextsDiagnostics - { - get; - set; - } - } -} diff --git a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalServerCapabilities.cs b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalServerCapabilities.cs index 2c42721af0edf..b8758f0f60161 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalServerCapabilities.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Internal/VSInternalServerCapabilities.cs @@ -99,17 +99,6 @@ public VSInternalDiagnosticOptions? DiagnosticProvider set; } - /// - /// Gets or sets a value indicating whether the server provides support for multiple context requests. - /// - [DataMember(Name = "_vs_MultipleContextSupportProvider")] - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public VSInternalMultipleContextFeatures? MultipleContextSupportProvider - { - get; - set; - } - /// /// Gets or sets a value indicating whether the server provides support for inline completion requests. /// diff --git a/src/Features/LanguageServer/Protocol/Protocol/LinkedEditingRangeOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/LinkedEditingRangeOptions.cs index 0afeffb82a826..4ad14537b3856 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/LinkedEditingRangeOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/LinkedEditingRangeOptions.cs @@ -20,10 +20,6 @@ internal class LinkedEditingRangeOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/ReferenceOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/ReferenceOptions.cs index 28efc1c1f90d4..a65a49c2b9046 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/ReferenceOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/ReferenceOptions.cs @@ -20,10 +20,6 @@ internal class ReferenceOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/RenameOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/RenameOptions.cs index 0b82f0e875713..f869eea186238 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/RenameOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/RenameOptions.cs @@ -31,10 +31,6 @@ public bool PrepareProvider /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenModifiers.cs b/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenModifiers.cs index 4505618601577..2c96ef5b846ce 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenModifiers.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenModifiers.cs @@ -64,8 +64,8 @@ internal static class SemanticTokenModifiers /// /// Collection containing all well-known semantic tokens modifiers. /// - public static readonly IReadOnlyList AllModifiers = new[] - { + public static readonly IReadOnlyList AllModifiers = + [ Declaration, Definition, Readonly, @@ -76,6 +76,6 @@ internal static class SemanticTokenModifiers Modification, Documentation, DefaultLibrary, - }; + ]; } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenTypes.cs b/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenTypes.cs index c4d4d4278729d..835e5d708cf35 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenTypes.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokenTypes.cs @@ -125,8 +125,8 @@ internal static class SemanticTokenTypes /// /// Collection containing all well-known semantic tokens types. /// - public static readonly IReadOnlyList AllTypes = new[] - { + public static readonly IReadOnlyList AllTypes = + [ Namespace, Type, Class, @@ -149,6 +149,6 @@ internal static class SemanticTokenTypes Number, Regexp, Operator, - }; + ]; } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokensOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokensOptions.cs index d3b2e6b98f9a1..99e483f5ecb47 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokensOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/SemanticTokens/SemanticTokensOptions.cs @@ -40,10 +40,6 @@ internal class SemanticTokensOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/SignatureHelpOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/SignatureHelpOptions.cs index 9f73e0c712e0a..9578bb1585af1 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/SignatureHelpOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/SignatureHelpOptions.cs @@ -43,10 +43,6 @@ public string[]? RetriggerCharacters /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/TypeDefinitionOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/TypeDefinitionOptions.cs index 480ddcd93f2ca..031e241a9fa5e 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/TypeDefinitionOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/TypeDefinitionOptions.cs @@ -20,10 +20,6 @@ internal class TypeDefinitionOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/Protocol/Protocol/WorkspaceSymbolOptions.cs b/src/Features/LanguageServer/Protocol/Protocol/WorkspaceSymbolOptions.cs index b3fc09e174d7d..8f2f697842d37 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/WorkspaceSymbolOptions.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/WorkspaceSymbolOptions.cs @@ -20,10 +20,6 @@ internal class WorkspaceSymbolOptions : IWorkDoneProgressOptions /// [DataMember(Name = "workDoneProgress")] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool WorkDoneProgress - { - get; - set; - } + public bool WorkDoneProgress { get; init; } } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs index fcd2cd0cf51b0..ae1624a02ec57 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionFeaturesTests.cs @@ -341,7 +341,7 @@ public void M(string someText) } else { - Assert.True(results.ItemDefaults.CommitCharacters.Length == 0); + Assert.Empty(results.ItemDefaults.CommitCharacters); Assert.True(!someTextItem.Preselect && someTextItem.CommitCharacters == null); } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs index 603f21bd9e255..1a8bae1134a27 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Completion/CompletionTests.cs @@ -639,7 +639,7 @@ void M() await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); var completionList = cache.GetCachedEntry(0).CompletionList; Assert.NotNull(completionList); - Assert.True(testAccessor.GetCacheContents().Count == 1); + Assert.Single(testAccessor.GetCacheContents()); // 2 items in cache await RunGetCompletionsAsync(testLspServer, completionParams).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Definitions/GoToDefinitionTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Definitions/GoToDefinitionTests.cs index 6f573aaeb6e8a..96b573de9de56 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Definitions/GoToDefinitionTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Definitions/GoToDefinitionTests.cs @@ -181,6 +181,26 @@ public partial class C AssertLocationsEqual(testLspServer.GetLocations("definition"), results); } + [Theory] + [InlineData("ValueTuple valueTuple1;")] + [InlineData("ValueTuple valueTuple2;")] + [InlineData("ValueTuple valueTuple3;")] + [InlineData("ValueTuple valueTuple4;")] + [InlineData("ValueTuple valueTuple5;")] + [InlineData("ValueTuple valueTuple6;")] + [InlineData("ValueTuple valueTuple7;")] + [InlineData("ValueTuple valueTuple8;")] + [WorkItem("https://github.com/dotnet/roslyn/issues/71680")] + public async Task TestGotoDefinitionWithValueTuple(string statement) + { + var markup = $"using System; {{|caret:|}}{statement}"; + + await using var testLspServer = await CreateTestLspServerAsync(markup, false); + + var results = await RunGotoDefinitionAsync(testLspServer, testLspServer.GetLocations("caret").Single()); + Assert.Single(results); + } + private static async Task RunGotoDefinitionAsync(TestLspServer testLspServer, LSP.Location caret) { return await testLspServer.ExecuteRequestAsync(LSP.Methods.TextDocumentDefinitionName, diff --git a/src/Features/Lsif/Generator/Generator.cs b/src/Features/Lsif/Generator/Generator.cs index b06accad75186..7439a53f8b431 100644 --- a/src/Features/Lsif/Generator/Generator.cs +++ b/src/Features/Lsif/Generator/Generator.cs @@ -86,7 +86,7 @@ public static Generator CreateAndWriteCapabilitiesVertex(ILsifJsonWriter lsifJso DocumentSymbolProvider, FoldingRangeProvider, DiagnosticProvider, - new SemanticTokensCapabilities(SemanticTokensSchema.LegacyTokensSchemaForLSIF.AllTokenTypes, new[] { SemanticTokenModifiers.Static })); + new SemanticTokensCapabilities(SemanticTokensSchema.LegacyTokensSchemaForLSIF.AllTokenTypes, [SemanticTokenModifiers.Static])); generator._lsifJsonWriter.Write(capabilitiesVertex); return generator; } diff --git a/src/Features/Test/EditAndContinue/EditAndContinueDiagnosticDescriptorsTests.cs b/src/Features/Test/EditAndContinue/EditAndContinueDiagnosticDescriptorsTests.cs index 81cc6b35365fc..760a33ac9c707 100644 --- a/src/Features/Test/EditAndContinue/EditAndContinueDiagnosticDescriptorsTests.cs +++ b/src/Features/Test/EditAndContinue/EditAndContinueDiagnosticDescriptorsTests.cs @@ -20,7 +20,7 @@ public void GetDescriptor() var d = EditAndContinueDiagnosticDescriptors.GetDescriptor(RudeEditKind.ActiveStatementUpdate); Assert.Equal("ENC0001", d.Id); Assert.Equal(DiagnosticCategory.EditAndContinue, d.Category); - Assert.Equal(new[] { "EditAndContinue", "Telemetry", "NotConfigurable", EnforceOnBuild.Never.ToCustomTag() }, d.CustomTags); + Assert.Equal(["EditAndContinue", "Telemetry", "NotConfigurable", EnforceOnBuild.Never.ToCustomTag()], d.CustomTags); Assert.Equal("", d.Description); Assert.Equal("", d.HelpLinkUri); Assert.Equal(new LocalizableResourceString(nameof(FeaturesResources.RudeEdit), FeaturesResources.ResourceManager, typeof(FeaturesResources)), d.Title); @@ -32,7 +32,7 @@ public void GetDescriptor() d = EditAndContinueDiagnosticDescriptors.GetDescriptor(EditAndContinueErrorCode.ErrorReadingFile); Assert.Equal("ENC1001", d.Id); Assert.Equal(DiagnosticCategory.EditAndContinue, d.Category); - Assert.Equal(new[] { "EditAndContinue", "Telemetry", "NotConfigurable", EnforceOnBuild.Never.ToCustomTag() }, d.CustomTags); + Assert.Equal(["EditAndContinue", "Telemetry", "NotConfigurable", EnforceOnBuild.Never.ToCustomTag()], d.CustomTags); Assert.Equal("", d.Description); Assert.Equal("", d.HelpLinkUri); Assert.Equal(new LocalizableResourceString(nameof(FeaturesResources.EditAndContinue), FeaturesResources.ResourceManager, typeof(FeaturesResources)), d.Title); @@ -42,7 +42,7 @@ public void GetDescriptor() d = EditAndContinueDiagnosticDescriptors.GetModuleDiagnosticDescriptor(ManagedHotReloadAvailabilityStatus.Optimized); Assert.Equal("ENC2012", d.Id); Assert.Equal(DiagnosticCategory.EditAndContinue, d.Category); - Assert.Equal(new[] { "EditAndContinue", "Telemetry", "NotConfigurable", EnforceOnBuild.Never.ToCustomTag() }, d.CustomTags); + Assert.Equal(["EditAndContinue", "Telemetry", "NotConfigurable", EnforceOnBuild.Never.ToCustomTag()], d.CustomTags); Assert.Equal("", d.Description); Assert.Equal("", d.HelpLinkUri); Assert.Equal(new LocalizableResourceString(nameof(FeaturesResources.EditAndContinue), FeaturesResources.ResourceManager, typeof(FeaturesResources)), d.Title); diff --git a/src/Features/Test/EditAndContinue/EditSessionActiveStatementsTests.cs b/src/Features/Test/EditAndContinue/EditSessionActiveStatementsTests.cs index b036c9743dbc3..3c721f2425433 100644 --- a/src/Features/Test/EditAndContinue/EditSessionActiveStatementsTests.cs +++ b/src/Features/Test/EditAndContinue/EditSessionActiveStatementsTests.cs @@ -325,7 +325,7 @@ static void F2() var updatedText = SourceText.From(updatedSource); var baseActiveStatementInfos = GetActiveStatementDebugInfosCSharp( - new[] { baseSource }, + [baseSource], modules: [module1, module1], methodVersions: [1, 1], flags: @@ -477,7 +477,7 @@ static void F4() var sourceTextV2 = SourceText.From(markedSourceV2); var sourceTextV3 = SourceText.From(markedSourceV3); - var activeStatementsPreRemap = GetActiveStatementDebugInfosCSharp(new[] { markedSourceV1 }, + var activeStatementsPreRemap = GetActiveStatementDebugInfosCSharp([markedSourceV1], modules: [module1, module1, module1, module1], methodVersions: [2, 2, 1, 1], // method F3 and F4 were not remapped flags: diff --git a/src/Features/Test/EditAndContinue/EmitSolutionUpdateResultsTests.cs b/src/Features/Test/EditAndContinue/EmitSolutionUpdateResultsTests.cs index e64407921ab36..cbd18a67521e3 100644 --- a/src/Features/Test/EditAndContinue/EmitSolutionUpdateResultsTests.cs +++ b/src/Features/Test/EditAndContinue/EmitSolutionUpdateResultsTests.cs @@ -86,8 +86,8 @@ public async Task GetHotReloadDiagnostics() helpLink: "http://link"); var rudeEdits = ImmutableArray.Create( - (document.Id, ImmutableArray.Create(new RudeEditDiagnostic(RudeEditKind.Insert, TextSpan.FromBounds(1, 10), 123, new[] { "a" }))), - (document.Id, ImmutableArray.Create(new RudeEditDiagnostic(RudeEditKind.Delete, TextSpan.FromBounds(1, 10), 123, new[] { "b" })))); + (document.Id, ImmutableArray.Create(new RudeEditDiagnostic(RudeEditKind.Insert, TextSpan.FromBounds(1, 10), 123, ["a"]))), + (document.Id, ImmutableArray.Create(new RudeEditDiagnostic(RudeEditKind.Delete, TextSpan.FromBounds(1, 10), 123, ["b"])))); var updateStatus = ModuleUpdateStatus.Blocked; var actual = await EmitSolutionUpdateResults.GetHotReloadDiagnosticsAsync(solution, diagnosticData, rudeEdits, syntaxError, updateStatus, CancellationToken.None); diff --git a/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs b/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs index a1602143f2a3d..c5fdc1551a471 100644 --- a/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs +++ b/src/Features/Test/EditAndContinue/RudeEditDiagnosticTests.cs @@ -88,7 +88,7 @@ public void ToDiagnostic() } else if (arg2.Contains(kind)) { - var re = new RudeEditDiagnostic(kind, TextSpan.FromBounds(1, 2), syntaxNode, new[] { "<1>", "<2>" }); + var re = new RudeEditDiagnostic(kind, TextSpan.FromBounds(1, 2), syntaxNode, ["<1>", "<2>"]); var d = re.ToDiagnostic(tree); Assert.True(d.GetMessage().Contains("<1>"), kind.ToString()); Assert.True(d.GetMessage().Contains("<2>"), kind.ToString()); @@ -96,7 +96,7 @@ public void ToDiagnostic() } else if (arg3.Contains(kind)) { - var re = new RudeEditDiagnostic(kind, TextSpan.FromBounds(1, 2), syntaxNode, new[] { "<1>", "<2>", "<3>" }); + var re = new RudeEditDiagnostic(kind, TextSpan.FromBounds(1, 2), syntaxNode, ["<1>", "<2>", "<3>"]); var d = re.ToDiagnostic(tree); Assert.True(d.GetMessage().Contains("<1>"), kind.ToString()); Assert.True(d.GetMessage().Contains("<2>"), kind.ToString()); @@ -105,7 +105,7 @@ public void ToDiagnostic() } else { - var re = new RudeEditDiagnostic(kind, TextSpan.FromBounds(1, 2), syntaxNode, new[] { "<1>" }); + var re = new RudeEditDiagnostic(kind, TextSpan.FromBounds(1, 2), syntaxNode, ["<1>"]); var d = re.ToDiagnostic(tree); Assert.True(d.GetMessage().Contains("<1>"), kind.ToString()); Assert.False(d.GetMessage().Contains("{"), kind.ToString()); diff --git a/src/NuGet/Microsoft.Net.Compilers.Toolset/README.md b/src/NuGet/Microsoft.Net.Compilers.Toolset/README.md index 40035272a5449..4754f3bcfd3ff 100644 --- a/src/NuGet/Microsoft.Net.Compilers.Toolset/README.md +++ b/src/NuGet/Microsoft.Net.Compilers.Toolset/README.md @@ -7,7 +7,7 @@ The underlying mechanism used is the same between all of the packages here but t - Microsoft.Net.Compilers.Toolset: this overrides the Roslyn compiler for both MSBuild and .NET SDK installations. This means it distributes both .NET Core and .NET Framework versions of our build tasks and compilers. It's meant as a way to hot patching bugs on customer machines and part of our mechanism for distributing the compiler in the .NET product build. It's not meant for or supported in general scenarios. - Microsoft.Net.Compilers.Toolset.Arm64: this package is functionally the same as Microsoft.Net.Compilers.Toolset except the .NET Framework binaries are targeted for ARM64 architectures. This provides the most efficiency for building on ARM64 machines environments. -- Microsoft.Net.Compilers.Toolset.Framework: this overrides the Roslyn compiler for MSBuild installations. This means it only distributes the .NET Framework versions of our build tasks and compilers which makes it significantly smaller than Microsoft.Net.Compilers.Toolset. This is used by the .NET SDK internally to ensure that using `msbuild` on a .NET SDK based project uses the version of Roslyn that shipped with the .NET SDK, not the one that happens to be installed for MSBuild. +- Microsoft.Net.Compilers.Toolset.Framework: this overrides the Roslyn compiler for MSBuild installations. This means it only distributes the .NET Framework versions of our build tasks and compilers which makes it significantly smaller than Microsoft.Net.Compilers.Toolset. This is used by the .NET SDK internally to ensure that using `msbuild` on a .NET SDK based project uses the version of Roslyn that shipped with the .NET SDK, not the one that happens to be installed for MSBuild. Users enable this by setting the property `BuildWithNetFrameworkHostedCompiler` to `true` ⚠️Warning⚠️ ️ diff --git a/src/Tools/AnalyzerRunner/CodeRefactoringRunner.cs b/src/Tools/AnalyzerRunner/CodeRefactoringRunner.cs index 3ccb3016db239..9e528f35e1d79 100644 --- a/src/Tools/AnalyzerRunner/CodeRefactoringRunner.cs +++ b/src/Tools/AnalyzerRunner/CodeRefactoringRunner.cs @@ -246,7 +246,7 @@ public CodeRefactoringProviderMetadata(IDictionary data) Languages = languages switch { IEnumerable values => values, - string value => new[] { value }, + string value => [value], _ => Array.Empty(), }; } diff --git a/src/Tools/BuildActionTelemetryTable/Program.cs b/src/Tools/BuildActionTelemetryTable/Program.cs index 9a67ee2101727..d03b7331e2d4e 100644 --- a/src/Tools/BuildActionTelemetryTable/Program.cs +++ b/src/Tools/BuildActionTelemetryTable/Program.cs @@ -678,7 +678,7 @@ internal static string GenerateCodeActionsDescriptionMap(ImmutableArray<(string builder.AppendLine(@$" {{ ""{actionOrProviderTypeName}"", ""{description}"" }},"); } - builder.Append("}"); + builder.Append('}'); return builder.ToString(); } diff --git a/src/Tools/BuildBoss/ProjectCheckerUtil.cs b/src/Tools/BuildBoss/ProjectCheckerUtil.cs index 2f8ac9a742752..9c7555b2d8081 100644 --- a/src/Tools/BuildBoss/ProjectCheckerUtil.cs +++ b/src/Tools/BuildBoss/ProjectCheckerUtil.cs @@ -255,6 +255,15 @@ private bool CheckTargetFrameworks(TextWriter textWriter) case "$(NetVSCode)": case "$(NetVSShared)": continue; + + case "$(NetRoslynBuildHostNetCoreVersion)": + { + // This property should only be used in one specific project + if (_data.FileName == "Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj") + continue; + else + break; + } } textWriter.WriteLine($"TargetFramework {targetFramework} is not supported in this build"); diff --git a/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageBraceMatcher.cs b/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageBraceMatcher.cs index 099b41fdc24e6..e441ba5fc5e45 100644 --- a/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageBraceMatcher.cs +++ b/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageBraceMatcher.cs @@ -15,10 +15,10 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.AspNetCore.Internal.EmbeddedLang { [ExportEmbeddedLanguageBraceMatcher( nameof(AspNetCoreEmbeddedLanguageBraceMatcher), - new[] { LanguageNames.CSharp }, + [LanguageNames.CSharp], supportsUnannotatedAPIs: false, // Add more syntax names here in the future if there are additional cases ASP.Net would like to light up on. - identifiers: new[] { "Route" }), Shared] + identifiers: ["Route"]), Shared] internal class AspNetCoreEmbeddedLanguageBraceMatcher : IEmbeddedLanguageBraceMatcher { [ImportingConstructor] diff --git a/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageClassifier.cs b/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageClassifier.cs index 9387445142ccc..71fce30024807 100644 --- a/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageClassifier.cs +++ b/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageClassifier.cs @@ -12,10 +12,10 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.AspNetCore.Internal.EmbeddedLang { [ExportEmbeddedLanguageClassifier( nameof(AspNetCoreEmbeddedLanguageClassifier), - new[] { LanguageNames.CSharp }, + [LanguageNames.CSharp], supportsUnannotatedAPIs: false, // Add more syntax names here in the future if there are additional cases ASP.Net would like to light up on. - identifiers: new[] { "Route" }), Shared] + identifiers: ["Route"]), Shared] internal class AspNetCoreEmbeddedLanguageClassifier : IEmbeddedLanguageClassifier { [ImportingConstructor] diff --git a/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageDocumentHighlighter.cs b/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageDocumentHighlighter.cs index e16ddcd894612..4e5ecc9662ed8 100644 --- a/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageDocumentHighlighter.cs +++ b/src/Tools/ExternalAccess/AspNetCore/Internal/EmbeddedLanguages/AspNetCoreEmbeddedLanguageDocumentHighlighter.cs @@ -14,10 +14,10 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.AspNetCore.Internal.EmbeddedLang { [ExportEmbeddedLanguageDocumentHighlighter( nameof(AspNetCoreEmbeddedLanguageDocumentHighlighter), - new[] { LanguageNames.CSharp }, + [LanguageNames.CSharp], supportsUnannotatedAPIs: false, // Add more syntax names here in the future if there are additional cases ASP.Net would like to light up on. - identifiers: new[] { "Route" }), Shared] + identifiers: ["Route"]), Shared] internal class AspNetCoreEmbeddedLanguageDocumentHighlighter : IEmbeddedLanguageDocumentHighlighter { [ImportingConstructor] diff --git a/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceFactory.cs b/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceFactory.cs deleted file mode 100644 index 4c4285eefcdec..0000000000000 --- a/src/Tools/IdeCoreBenchmarks/CloudCache/IdeCoreBenchmarksCloudCacheServiceFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -using System; -using System.Composition; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Storage; -using Microsoft.CodeAnalysis.Storage.CloudCache; -using Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks; - -namespace CloudCache -{ - [ExportWorkspaceServiceFactory(typeof(ICloudCacheStorageService), ServiceLayer.Host), Shared] - internal class IdeCoreBenchmarksCloudCacheServiceFactory : IWorkspaceServiceFactory - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public IdeCoreBenchmarksCloudCacheServiceFactory() - { - Console.WriteLine($"Instantiated {nameof(IdeCoreBenchmarksCloudCacheServiceFactory)}"); - } - - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - => new MockCloudCachePersistentStorageService(workspaceServices.GetRequiredService(), @"C:\github\roslyn"); - } -} diff --git a/src/Tools/IdeCoreBenchmarks/IdeCoreBenchmarks.csproj b/src/Tools/IdeCoreBenchmarks/IdeCoreBenchmarks.csproj index f227201d4a49a..c05b0e6add8d7 100644 --- a/src/Tools/IdeCoreBenchmarks/IdeCoreBenchmarks.csproj +++ b/src/Tools/IdeCoreBenchmarks/IdeCoreBenchmarks.csproj @@ -12,17 +12,6 @@ $(NoWarn);NETSDK1206 - - - - - - - - - - - diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/AbstractFileWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/AbstractFileWriter.cs index ae79b7308004f..2931817739a25 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/AbstractFileWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/AbstractFileWriter.cs @@ -111,7 +111,7 @@ protected string CommaJoin(params object[] values) protected string Join(string separator, params object[] values) => string.Join(separator, values.SelectMany(v => (v switch { - string s => new[] { s }, + string s => [s], IEnumerable ss => ss, _ => throw new InvalidOperationException("Join must be passed strings or collections of strings") }).Where(s => s != ""))); diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/string-resources.json b/src/VisualStudio/CSharp/Impl/.vsextension/string-resources.json new file mode 100644 index 0000000000000..f76e640222c15 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/string-resources.json @@ -0,0 +1,5 @@ +{ + "CSharpLanguageServiceExtension.OpenInteractiveWindow.DisplayName": "C# Interactive", + "CSharpLanguageServiceExtension.ResetInteractiveWindowFromProject.DisplayName": "Initialize Interactive with Project", + "CSharpLanguageServiceExtension.OpenSemanticSearchWindow.DisplayName": "C# Semantic Search" +} diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.cs.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.cs.xlf new file mode 100644 index 0000000000000..690ce89eb11d0 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.cs.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.de.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.de.xlf new file mode 100644 index 0000000000000..7b7cccfec5b52 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.de.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.es.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.es.xlf new file mode 100644 index 0000000000000..9b962e84d5f16 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.es.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.fr.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.fr.xlf new file mode 100644 index 0000000000000..6dae65fe61cbf --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.fr.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.it.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.it.xlf new file mode 100644 index 0000000000000..ededa633cd4d3 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.it.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ja.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ja.xlf new file mode 100644 index 0000000000000..6b3b47991c93d --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ja.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ko.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ko.xlf new file mode 100644 index 0000000000000..2ebb6cb7a2b11 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ko.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.pl.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.pl.xlf new file mode 100644 index 0000000000000..1829759bfe220 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.pl.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.pt-BR.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.pt-BR.xlf new file mode 100644 index 0000000000000..174a159ee952c --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.pt-BR.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ru.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ru.xlf new file mode 100644 index 0000000000000..03fb7affc7311 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.ru.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.tr.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.tr.xlf new file mode 100644 index 0000000000000..b4d9c1193c701 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.tr.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.zh-Hans.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.zh-Hans.xlf new file mode 100644 index 0000000000000..c34d2b5c61d76 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.zh-Hans.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.zh-Hant.xlf b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.zh-Hant.xlf new file mode 100644 index 0000000000000..7b0bf4cdbfba8 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/.vsextension/xlf/string-resources.json.zh-Hant.xlf @@ -0,0 +1,22 @@ + + + + + + C# Interactive + C# Interactive + + + + C# Semantic Search + C# Semantic Search + + + + Initialize Interactive with Project + Initialize Interactive with Project + + + + + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/CSharpExtension.cs b/src/VisualStudio/CSharp/Impl/CSharpExtension.cs new file mode 100644 index 0000000000000..86969cdd5f05e --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/CSharpExtension.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. + +using System; +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.LanguageServices.CSharp.Interactive; +using Microsoft.VisualStudio.Shell; + +namespace Microsoft.VisualStudio.LanguageServices; + +[VisualStudioContribution] +internal sealed class CSharpExtension : Extension +{ + public override ExtensionConfiguration ExtensionConfiguration => new() + { + RequiresInProcessHosting = true, + }; + + [VisualStudioContribution] + public static CommandGroupConfiguration ProjectCommandGroupWithPlacement + => new(GroupPlacement.VsctParent(new Guid(VSConstants.CMDSETID.ShellMainMenu_string), VsMenus.IDM_VS_CTXT_PROJNODE, priority: 0x0400)) + { + Children = new[] + { + GroupChild.Command() + } + }; +} diff --git a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeNameGenerator.cs b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeNameGenerator.cs index b16f172ba5a9c..4916e381bda78 100644 --- a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeNameGenerator.cs +++ b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeNameGenerator.cs @@ -115,7 +115,7 @@ private static void AppendParameterList(StringBuilder builder, BaseParameterList { if (firstSeen) { - builder.Append(","); + builder.Append(','); } if (parameter.Modifiers.Any(SyntaxKind.RefKeyword)) diff --git a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService_Prototype.cs b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService_Prototype.cs index 657320121e65f..888846f199862 100644 --- a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService_Prototype.cs +++ b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService_Prototype.cs @@ -462,7 +462,7 @@ private void AppendPropertyPrototype(StringBuilder builder, IPropertySymbol symb { builder.Append("this["); AppendParametersPrototype(builder, symbol.Parameters, PrototypeFlags.ParameterTypes | PrototypeFlags.ParameterNames); - builder.Append("]"); + builder.Append(']'); } else { diff --git a/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsInteractiveWindowPackage.cs b/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsInteractiveWindowPackage.cs index 1fccfd287a94f..51286a17afe58 100644 --- a/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsInteractiveWindowPackage.cs +++ b/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsInteractiveWindowPackage.cs @@ -2,40 +2,19 @@ // 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; -using System.ComponentModel.Design; using System.Runtime.InteropServices; using Microsoft.VisualStudio.LanguageServices.Interactive; -using Microsoft.VisualStudio.Shell; using LanguageServiceGuids = Microsoft.VisualStudio.LanguageServices.Guids; -namespace Microsoft.VisualStudio.LanguageServices.CSharp.Interactive -{ - [Guid(LanguageServiceGuids.CSharpReplPackageIdString)] - internal sealed partial class CSharpVsInteractiveWindowPackage : VsInteractiveWindowPackage - { - private const string IdString = "CA8CC5C7-0231-406A-95CD-AA5ED6AC0190"; - internal static readonly Guid Id = new(IdString); - - protected override Guid ToolWindowId - { - get { return Id; } - } +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Interactive; - protected override Guid LanguageServiceGuid - { - get { return LanguageServiceGuids.CSharpLanguageServiceId; } - } - - protected override void InitializeMenuCommands(OleMenuCommandService menuCommandService) - { - var openInteractiveCommand = new MenuCommand( - (sender, args) => this.InteractiveWindowProvider.Open(instanceId: 0, focus: true), - new CommandID(ID.InteractiveCommands.CSharpInteractiveCommandSetId, ID.InteractiveCommands.InteractiveToolWindow)); +[Guid(LanguageServiceGuids.CSharpReplPackageIdString)] +internal sealed partial class CSharpVsInteractiveWindowPackage : VsInteractiveWindowPackage +{ + private const string IdString = "CA8CC5C7-0231-406A-95CD-AA5ED6AC0190"; + internal static readonly Guid Id = new(IdString); - menuCommandService.AddCommand(openInteractiveCommand); - } - } + protected override Guid ToolWindowId => Id; + protected override Guid LanguageServiceGuid => LanguageServiceGuids.CSharpLanguageServiceId; } diff --git a/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsResetInteractiveCommand.cs b/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsResetInteractiveCommand.cs deleted file mode 100644 index f2afd8c007cda..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/CSharpVsResetInteractiveCommand.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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 disable - -using Microsoft.CodeAnalysis.Editor; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.VisualStudio.Shell; -using Roslyn.VisualStudio.Services.Interactive; -using System; -using System.ComponentModel.Composition; - -namespace Microsoft.VisualStudio.LanguageServices.CSharp.Interactive -{ - [ExportInteractive(typeof(IResetInteractiveCommand), ContentTypeNames.CSharpContentType)] - internal sealed class CSharpVsResetInteractiveCommand - : AbstractResetInteractiveCommand - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpVsResetInteractiveCommand( - VisualStudioWorkspace workspace, - CSharpVsInteractiveWindowProvider interactiveWindowProvider, - [Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) - : base(workspace, interactiveWindowProvider, serviceProvider) - { - } - - protected override string LanguageName - { - get { return "C#"; } - } - - protected override string CreateReference(string referenceName) - => string.Format("#r \"{0}\"", referenceName); - - protected override string CreateImport(string namespaceName) - => string.Format("using {0};", namespaceName); - } -} diff --git a/src/VisualStudio/CSharp/Impl/Interactive/Commands.vsct b/src/VisualStudio/CSharp/Impl/Interactive/Commands.vsct deleted file mode 100644 index 4bd14cec12bd8..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/Commands.vsct +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/VisualStudio/CSharp/Impl/Interactive/OpenInteractiveWindowCommand.cs b/src/VisualStudio/CSharp/Impl/Interactive/OpenInteractiveWindowCommand.cs new file mode 100644 index 0000000000000..9e1504dd602c4 --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/Interactive/OpenInteractiveWindowCommand.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. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.VSSdkCompatibility; +using Microsoft.VisualStudio.Threading; +using Roslyn.Utilities; + +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Interactive; + +/// +/// Implements View/Other Windows/C# Interactive command. +/// +[VisualStudioContribution] +internal class OpenInteractiveWindowCommand( + MefInjection mefThreadingContext, + MefInjection mefInteractiveWindowProvider) : Command +{ + public override CommandConfiguration CommandConfiguration => new("%CSharpLanguageServiceExtension.OpenInteractiveWindow.DisplayName%") + { + Placements = new[] { CommandPlacement.KnownPlacements.ViewOtherWindowsMenu.WithPriority(0x8000) }, + // TODO: Shortcuts https://github.com/dotnet/roslyn/issues/3941 + }; + + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + var threadingContext = await mefThreadingContext.GetServiceAsync().ConfigureAwait(false); + var interactiveWindowProvider = await mefInteractiveWindowProvider.GetServiceAsync().ConfigureAwait(false); + + await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + _ = interactiveWindowProvider.Open(instanceId: 0, focus: true); + } +} diff --git a/src/VisualStudio/CSharp/Impl/Interactive/ResetInteractiveWindowFromProjectCommand.cs b/src/VisualStudio/CSharp/Impl/Interactive/ResetInteractiveWindowFromProjectCommand.cs new file mode 100644 index 0000000000000..e5dff8f393dbf --- /dev/null +++ b/src/VisualStudio/CSharp/Impl/Interactive/ResetInteractiveWindowFromProjectCommand.cs @@ -0,0 +1,80 @@ +// 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. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.Extensibility; +using Microsoft.VisualStudio.Extensibility.Commands; +using Microsoft.VisualStudio.Extensibility.VSSdkCompatibility; +using Microsoft.VisualStudio.LanguageServices.Interactive; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.VisualStudio.LanguageServices.CSharp.Interactive; + +/// +/// Implements View/Other Windows/C# Interactive command. +/// +[VisualStudioContribution] +internal class ResetInteractiveWindowFromProjectCommand( + MefInjection mefThreadingContext, + MefInjection mefInteractiveWindowProvider, + MefInjection mefWorkspace, + MefInjection mefUIThreadOperationExecutor, + MefInjection mefEditorOptionsService, + AsyncServiceProviderInjection dteProvider, + AsyncServiceProviderInjection monitorSelectionProvider, + AsyncServiceProviderInjection solutionBuildManagerProvider) : Command +{ + public override CommandConfiguration CommandConfiguration => new("%CSharpLanguageServiceExtension.ResetInteractiveWindowFromProject.DisplayName%") + { + VisibleWhen = + ActivationConstraint.ActiveProjectCapability(ProjectCapability.CSharp) & + // This doesn't activate when a multi-targeted project has a netfx target. We currently do not support that scenario. + // Ideally, we would remove this constraint entirely and support reset for .NET as well. + ActivationConstraint.ActiveProjectBuildProperty("TargetFrameworkMoniker", "[.]NETFramework.*") + }; + + public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) + { + var threadingContext = await mefThreadingContext.GetServiceAsync().ConfigureAwait(false); + var interactiveWindowProvider = await mefInteractiveWindowProvider.GetServiceAsync().ConfigureAwait(false); + var workspace = await mefWorkspace.GetServiceAsync().ConfigureAwait(false); + var editorOptionsService = await mefEditorOptionsService.GetServiceAsync().ConfigureAwait(false); + var uiThreadOperationExecutor = await mefUIThreadOperationExecutor.GetServiceAsync().ConfigureAwait(false); + + await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + + // fetch services on UI thread and stay on UI thread: + var dte = await dteProvider.GetServiceAsync().ConfigureAwait(true); + var monitorSelection = await monitorSelectionProvider.GetServiceAsync().ConfigureAwait(true); + var solutionBuildManager = await solutionBuildManagerProvider.GetServiceAsync().ConfigureAwait(true); + + var resetInteractive = new VsResetInteractive( + workspace, + dte, + editorOptionsService, + uiThreadOperationExecutor, + monitorSelection, + solutionBuildManager, + static referenceName => $"#r \"{referenceName}\"", + static namespaceName => $"using {namespaceName};"); + + var vsInteractiveWindow = interactiveWindowProvider.Open(instanceId: 0, focus: true); + + // TODO: potential race condition (https://github.com/dotnet/roslyn/issues/71871): + await resetInteractive.ExecuteAsync(vsInteractiveWindow.InteractiveWindow, CSharpVSResources.CSharp_Interactive).ConfigureAwait(true); + resetInteractive.ExecutionCompleted += FocusWindow; + + void FocusWindow(object s, EventArgs e) + { + // We have to set focus to the Interactive Window *after* the wait indicator is dismissed. + vsInteractiveWindow.Show(focus: true); + resetInteractive.ExecutionCompleted -= FocusWindow; + } + } +} diff --git a/src/VisualStudio/CSharp/Impl/Interactive/Resources/ScriptFile.ico b/src/VisualStudio/CSharp/Impl/Interactive/Resources/ScriptFile.ico deleted file mode 100644 index 6f31473654cf2..0000000000000 Binary files a/src/VisualStudio/CSharp/Impl/Interactive/Resources/ScriptFile.ico and /dev/null differ diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.cs.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.cs.xlf deleted file mode 100644 index 8d47faa63452f..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.cs.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interactive - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.de.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.de.xlf deleted file mode 100644 index cdb7445645464..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.de.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interactive - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.es.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.es.xlf deleted file mode 100644 index e446dc5c13822..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.es.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# interactivo - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.fr.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.fr.xlf deleted file mode 100644 index e0bba3418ffdb..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.fr.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interactive - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.it.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.it.xlf deleted file mode 100644 index a804712824901..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.it.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interactive - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ja.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ja.xlf deleted file mode 100644 index 78efb35cd9c8d..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ja.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# インタラクティブ - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ko.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ko.xlf deleted file mode 100644 index 6c2e10ed40046..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ko.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# 대화형 - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.pl.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.pl.xlf deleted file mode 100644 index 5dbd3b07ce19a..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.pl.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interactive - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.pt-BR.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.pt-BR.xlf deleted file mode 100644 index 2d0d67a22af06..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.pt-BR.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interativo - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ru.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ru.xlf deleted file mode 100644 index 5edbf3039ff67..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.ru.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Interactive - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.tr.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.tr.xlf deleted file mode 100644 index cda4664ab82c7..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.tr.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# Etkileşimli - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.zh-Hans.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.zh-Hans.xlf deleted file mode 100644 index 0e96e8e59b988..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.zh-Hans.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# 交互窗口 - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.zh-Hant.xlf b/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.zh-Hant.xlf deleted file mode 100644 index 8ffcebe6e1215..0000000000000 --- a/src/VisualStudio/CSharp/Impl/Interactive/xlf/Commands.vsct.zh-Hant.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - C# Interactive - C# 互動 - - - - - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj b/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj index 0f98c5ca6f5c8..c5cfdf4c133f7 100644 --- a/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj +++ b/src/VisualStudio/CSharp/Impl/Microsoft.VisualStudio.LanguageServices.CSharp.csproj @@ -14,7 +14,11 @@ false true false + true + + + @@ -37,6 +41,8 @@ + + @@ -52,10 +58,5 @@ VSPackage Designer - - - Menus.ctmenu - Designer - \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf index 2ea9959d8faf6..f6377d71c9dc1 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# Interactive diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf index 6484753fec085..eaca3c16844e5 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# Interactive diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf index 1bf1d16ff3664..ec177d35f3e23 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# インタラクティブ diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf index 97a59a92aec94..e301708356143 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# Interactive diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf index 4a9ab0d8f8bd3..a50df565bda4b 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# Interativo diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf index b1f26c7e9c7b4..3d7963616bcec 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# Etkileşimli diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf index d67a6c4bf228c..9eda48bf09f9d 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf @@ -59,7 +59,7 @@ C# Interactive - C# Interactive + C# 互動 diff --git a/src/VisualStudio/CSharp/Test/CallHierarchy/CSharpCallHierarchyTests.cs b/src/VisualStudio/CSharp/Test/CallHierarchy/CSharpCallHierarchyTests.cs index 1ea03daae0b8a..e1b1bf3a44b7b 100644 --- a/src/VisualStudio/CSharp/Test/CallHierarchy/CSharpCallHierarchyTests.cs +++ b/src/VisualStudio/CSharp/Test/CallHierarchy/CSharpCallHierarchyTests.cs @@ -440,8 +440,7 @@ public override void Goo() testState.VerifyResult(root, EditorFeaturesResources.Overrides_, ["N.G.Goo()"]); } - [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844613")] - [WpfFact] + [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844613")] public async Task AbstractMethodInclusionToOverrides() { var text = @" @@ -492,8 +491,7 @@ void M() testState.VerifyResult(root, string.Format(EditorFeaturesResources.Calls_To_0, "Goo"), expectedCallers: ["N.C.M()"]); } - [WorkItem("https://github.com/dotnet/roslyn/issues/57856")] - [WpfFact] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/57856")] public async Task PropertySet() { var code = @" diff --git a/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs b/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs index 187c6f2f057bf..c412b53e936d2 100644 --- a/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs +++ b/src/VisualStudio/CSharp/Test/DocumentOutline/DocumentOutlineTests.cs @@ -150,8 +150,7 @@ public async Task TestSearchDocumentSymbolData() Assert.Equal(0, searchedSymbols.Length); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/66012")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/66012")] public async Task TestEnumOnSingleLine() { var (_, _, items) = await InitializeMocksAndDataModelAndUIItems( @@ -181,8 +180,7 @@ enum Test }); } - [WpfFact] - [WorkItem("https://github.com/dotnet/roslyn/issues/66473")] + [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/66473")] public async Task TestClassOnSingleLine() { var (_, _, items) = await InitializeMocksAndDataModelAndUIItems( diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs deleted file mode 100644 index 4c22d111f8630..0000000000000 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/CloudCachePersistentStorageTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -using System; -using System.Linq; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Storage; -using Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks; - -namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices -{ - public class CloudCachePersistentStorageTests : AbstractPersistentStorageTests - { - internal override AbstractPersistentStorageService GetStorageService( - IMefHostExportProvider exportProvider, IPersistentStorageConfiguration configuration, IPersistentStorageFaultInjector? faultInjector, string relativePathBase) - { - return new MockCloudCachePersistentStorageService(configuration, relativePathBase); - } - } -} diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/AuthorizationServiceMock.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/AuthorizationServiceMock.cs deleted file mode 100644 index 405d6af003f63..0000000000000 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/AuthorizationServiceMock.cs +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -// Copy of https://devdiv.visualstudio.com/DevDiv/_git/VS.CloudCache?path=%2Ftest%2FMicrosoft.VisualStudio.Cache.Tests%2FMocks&_a=contents&version=GBmain -// Try to keep in sync and avoid unnecessary changes here. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.ServiceHub.Framework.Services; - -#pragma warning disable CS0067 // events that are never used - -namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks -{ - internal class AuthorizationServiceMock : IAuthorizationService - { - public event EventHandler? CredentialsChanged; - - public event EventHandler? AuthorizationChanged; - - internal bool Allow { get; set; } = true; - - public ValueTask CheckAuthorizationAsync(ProtectedOperation operation, CancellationToken cancellationToken = default) - { - return new ValueTask(this.Allow); - } - - public ValueTask> GetCredentialsAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/FileSystemServiceMock.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/FileSystemServiceMock.cs deleted file mode 100644 index 58009779502fb..0000000000000 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/FileSystemServiceMock.cs +++ /dev/null @@ -1,89 +0,0 @@ -// 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. - -// Copy of https://devdiv.visualstudio.com/DevDiv/_git/VS.CloudCache?path=%2Ftest%2FMicrosoft.VisualStudio.Cache.Tests%2FMocks&_a=contents&version=GBmain -// Try to keep in sync and avoid unnecessary changes here. - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Pipelines; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.ServiceHub.Framework; -using Microsoft.VisualStudio.RpcContracts.FileSystem; - -namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks -{ - internal class FileSystemServiceMock : IFileSystem - { - public event EventHandler? DirectoryEntryChanged; - - public event EventHandler? RootEntriesChanged; - - public Task ConvertLocalFileNameToRemoteUriAsync(string fileName, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task ConvertLocalFileNameToRemoteUriAsync(string fileName, string remoteScheme, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task ConvertLocalUriToRemoteUriAsync(Uri localUri, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task ConvertLocalUriToRemoteUriAsync(Uri localUri, string remoteScheme, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task ConvertRemoteFileNameToRemoteUriAsync(string _1, CancellationToken _2) => throw new NotImplementedException(); - - public Task ConvertRemoteFileNameToRemoteUriAsync(string _1, string _2, CancellationToken _3) => throw new NotImplementedException(); - - public Task ConvertRemoteUriToLocalUriAsync(Uri remoteUri, CancellationToken cancellationToken) => Task.FromResult(remoteUri); - - public Task ConvertRemoteUriToRemoteFileNameAsync(Uri _1, CancellationToken _2) => throw new NotImplementedException(); - - public Task CopyAsync(Uri sourceUri, Uri destinationUri, bool overwrite, IProgress? progress, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task CreateDirectoryAsync(Uri uri, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task DeleteAsync(Uri uri, bool recursive, IProgress? progress, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task DownloadFileAsync(Uri remoteUri, IProgress? progress, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public IAsyncEnumerable EnumerateDirectoriesAsync(Uri uri, string searchPattern, SearchOption searchOption, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public IAsyncEnumerable EnumerateDirectoryEntriesAsync(Uri uri, string searchPattern, SearchOption searchOption, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public IAsyncEnumerable EnumerateFilesAsync(Uri uri, string searchPattern, SearchOption searchOption, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task GetDefaultRemoteUriSchemeAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task GetDisplayInfoAsync(Uri uri, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task GetDisplayInfoAsync(string fileName, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task GetInfoAsync(Uri uri, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task GetMonikerForFileSystemProviderAsync(string scheme, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task GetMonikerForRemoteFileSystemProviderAsync(string scheme, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task> GetRootEntriesAsync(string scheme, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task> GetRootEntriesAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task> GetSupportedSchemesAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task MoveAsync(Uri oldUri, Uri newUri, bool overwrite, IProgress? progress, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task ReadFileAsync(Uri uri, PipeWriter writer, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask UnwatchAsync(WatchResult watchResult, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask WatchDirectoryAsync(Uri uri, bool recursive, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask WatchFileAsync(Uri uri, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task WriteFileAsync(Uri uri, PipeReader reader, bool overwrite, CancellationToken cancellationToken) => throw new NotImplementedException(); - - protected virtual void OnDirectoryEntryChanged(DirectoryEntryChangedEventArgs args) => this.DirectoryEntryChanged?.Invoke(this, args); - - protected virtual void OnRootEntriesChanged(RootEntriesChangedEventArgs args) => this.RootEntriesChanged?.Invoke(this, args); - } -} diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs deleted file mode 100644 index f15e26293d483..0000000000000 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/MockCloudCachePersistentStorageService.cs +++ /dev/null @@ -1,54 +0,0 @@ -// 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. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.ServiceHub.Framework; -using Microsoft.ServiceHub.Framework.Services; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.Cache; -using Microsoft.VisualStudio.Cache.SQLite; -using Microsoft.VisualStudio.LanguageServices.Storage; -using Microsoft.VisualStudio.RpcContracts.Caching; - -namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks -{ - internal class MockCloudCachePersistentStorageService : AbstractCloudCachePersistentStorageService - { - private readonly string _relativePathBase; - - public MockCloudCachePersistentStorageService( - IPersistentStorageConfiguration configuration, - string relativePathBase) - : base(configuration) - { - _relativePathBase = relativePathBase; - } - - protected override async ValueTask CreateCacheServiceAsync(string solutionFolder, CancellationToken cancellationToken) - { - // Directly access VS' CacheService through their library and not as a brokered service. Then create our - // wrapper CloudCacheService directly on that instance. - var authorizationServiceClient = new AuthorizationServiceClient(new AuthorizationServiceMock()); - var solutionService = new SolutionServiceMock(); - var fileSystem = new FileSystemServiceMock(); - var serviceBroker = new ServiceBrokerMock() - { - BrokeredServices = - { - { VisualStudioServices.VS2019_10.SolutionService.Moniker, solutionService }, - { VisualStudioServices.VS2019_10.FileSystem.Moniker, fileSystem }, - { FrameworkServices.Authorization.Moniker, new AuthorizationServiceMock() }, - }, - }; - - var someContext = new CacheContext { RelativePathBase = _relativePathBase }; - var pool = new SqliteConnectionPool(); - var activeContext = await pool.ActivateContextAsync(someContext, default); - var cacheService = new CacheService(activeContext, serviceBroker, authorizationServiceClient, pool); - return cacheService; - } - } -} diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/ServiceBrokerMock.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/ServiceBrokerMock.cs deleted file mode 100644 index 8a32ef1b221b9..0000000000000 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/ServiceBrokerMock.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -// Copy of https://devdiv.visualstudio.com/DevDiv/_git/VS.CloudCache?path=%2Ftest%2FMicrosoft.VisualStudio.Cache.Tests%2FMocks&_a=contents&version=GBmain -// Try to keep in sync and avoid unnecessary changes here. - -using System; -using System.Collections.Generic; -using System.IO.Pipelines; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.ServiceHub.Framework; - -namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks -{ - internal class ServiceBrokerMock : IServiceBroker - { - public event EventHandler? AvailabilityChanged; - - internal Dictionary BrokeredServices { get; } = new(); - - public ValueTask GetPipeAsync(ServiceMoniker serviceMoniker, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public ValueTask GetProxyAsync(ServiceRpcDescriptor serviceDescriptor, ServiceActivationOptions options = default, CancellationToken cancellationToken = default) - where T : class - { - if (this.BrokeredServices.TryGetValue(serviceDescriptor.Moniker, out var service)) - { - return new((T?)service); - } - - return default; - } - - internal void OnAvailabilityChanged(BrokeredServicesChangedEventArgs args) => this.AvailabilityChanged?.Invoke(this, args); - } -} diff --git a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/SolutionServiceMock.cs b/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/SolutionServiceMock.cs deleted file mode 100644 index 0819ce75e36df..0000000000000 --- a/src/VisualStudio/CSharp/Test/PersistentStorage/Mocks/SolutionServiceMock.cs +++ /dev/null @@ -1,104 +0,0 @@ -// 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. - -// Copy of https://devdiv.visualstudio.com/DevDiv/_git/VS.CloudCache?path=%2Ftest%2FMicrosoft.VisualStudio.Cache.Tests%2FMocks&_a=contents&version=GBmain -// Try to keep in sync and avoid unnecessary changes here. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using System.Threading.Tasks.Dataflow; -using Microsoft.VisualStudio.RpcContracts.Solution; -using Microsoft.VisualStudio.Threading; - -#pragma warning disable CS0067 // events that are never used - -namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks -{ - internal class SolutionServiceMock : ISolutionService - { - private readonly BroadcastObservable openContainerObservable = new BroadcastObservable(new OpenCodeContainersState()); - - public event EventHandler? ProjectsLoaded; - - public event EventHandler? ProjectsUnloaded; - - public event EventHandler? ProjectLoadProgressChanged; - - internal Uri? SolutionFilePath - { - get => this.openContainerObservable.Value.SolutionFilePath; - set => this.openContainerObservable.Value = this.openContainerObservable.Value with { SolutionFilePath = value }; - } - - public ValueTask AreProjectsLoadedAsync(Guid[] projectIds, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task SubscribeToOpenCodeContainersStateAsync(IObserver observer, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - return Task.FromResult(this.openContainerObservable.Subscribe(observer)); - } - - public Task GetOpenCodeContainersStateAsync(CancellationToken cancellationToken) => Task.FromResult(this.openContainerObservable.Value); - - public Task CloseSolutionAndFolderAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask> GetPropertyValuesAsync(IReadOnlyList propertyIds, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask> GetSolutionTelemetryContextPropertyValuesAsync(IReadOnlyList propertyNames, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask LoadProjectsAsync(Guid[] projectIds, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask LoadProjectsWithResultAsync(Guid[] projectIds, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask RemoveProjectsAsync(IReadOnlyList projectIds, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task RequestProjectEventsAsync(CancellationToken cancellationToken) => throw new NotImplementedException(); - - public Task SaveSolutionFilterFileAsync(string filterFileDirectory, string filterFileName, CancellationToken cancellationToken) => throw new NotImplementedException(); - - public ValueTask UnloadProjectsAsync(Guid[] projectIds, ProjectUnloadReason unloadReason, CancellationToken cancellationToken) => throw new NotImplementedException(); - - internal void SimulateFolderChange(IReadOnlyList folderPaths) => this.openContainerObservable.Value = this.openContainerObservable.Value with { OpenFolderPaths = folderPaths }; - - private class BroadcastObservable : IObservable - { - private readonly BroadcastBlock sourceBlock = new(v => v); - private T value; - - internal BroadcastObservable(T initialValue) - { - this.sourceBlock.Post(this.value = initialValue); - } - - internal T Value - { - get => this.value; - set => this.sourceBlock.Post(this.value = value); - } - - public IDisposable Subscribe(IObserver observer) - { - var actionBlock = new ActionBlock(observer.OnNext); - actionBlock.Completion.ContinueWith( - static (t, s) => - { - var observer = (IObserver)s!; - if (t.Exception is object) - { - observer.OnError(t.Exception); - } - else - { - observer.OnCompleted(); - } - }, - observer, - TaskScheduler.Default).Forget(); - return this.sourceBlock.LinkTo(actionBlock, new DataflowLinkOptions { PropagateCompletion = true }); - } - } - } -} diff --git a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/CSharpCompilerOptionsTests.cs b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/CSharpCompilerOptionsTests.cs index fb67b709c3197..95a341d45143b 100644 --- a/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/CSharpCompilerOptionsTests.cs +++ b/src/VisualStudio/CSharp/Test/ProjectSystemShim/CPS/CSharpCompilerOptionsTests.cs @@ -90,12 +90,19 @@ public async Task ProjectOutputBinPathChange_CPS() Assert.Equal(newObjPath, project.CompilationOutputAssemblyFilePath); Assert.Equal(newBinPath, project.BinOutputPath); - // Change bin output folder to non-normalized path - verify that binOutputPath changes to normalized path, but objOutputPath is the same. + // Change bin output folder to non-absolute path - verify that binOutputPath changes to normalized path, but objOutputPath is the same. newBinPath = @"test.dll"; var expectedNewBinPath = Path.Combine(Path.GetTempPath(), newBinPath); project.BinOutputPath = newBinPath; Assert.Equal(newObjPath, project.CompilationOutputAssemblyFilePath); Assert.Equal(expectedNewBinPath, project.BinOutputPath); + + // Change obj folder to non-canonical path - verify that objOutputPath changes to normalized path, but binOutputPath is unchanged. + var relativeObjPath = @"..\folder\\test.dll"; + var absoluteObjPath = Path.GetFullPath(Path.Combine(Path.GetTempPath(), relativeObjPath)); + project.SetOptions(ImmutableArray.Create($"/out:{relativeObjPath}")); + Assert.Equal(absoluteObjPath, project.CompilationOutputAssemblyFilePath); + Assert.Equal(expectedNewBinPath, project.BinOutputPath); } [WpfFact] diff --git a/src/VisualStudio/Core/Def/ErrorReporting/VisualStudioErrorReportingService.ExceptionFormatting.cs b/src/VisualStudio/Core/Def/ErrorReporting/VisualStudioErrorReportingService.ExceptionFormatting.cs index 2fa062a5a0699..eabc05902f43e 100644 --- a/src/VisualStudio/Core/Def/ErrorReporting/VisualStudioErrorReportingService.ExceptionFormatting.cs +++ b/src/VisualStudio/Core/Def/ErrorReporting/VisualStudioErrorReportingService.ExceptionFormatting.cs @@ -153,7 +153,7 @@ private static bool FormatMethodName(StringBuilder stringBuilder, Type declaring else { stringBuilder.Append(fullName); - stringBuilder.Append("."); + stringBuilder.Append('.'); return false; } } diff --git a/src/VisualStudio/Core/Def/ID.InteractiveCommands.cs b/src/VisualStudio/Core/Def/ID.InteractiveCommands.cs deleted file mode 100644 index 60ce0f5c68d94..0000000000000 --- a/src/VisualStudio/Core/Def/ID.InteractiveCommands.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -using System; - -namespace Microsoft.VisualStudio.LanguageServices -{ - internal static partial class ID - { - internal static class InteractiveCommands - { - public const int InteractiveToolWindow = 0x0001; - public const int ResetInteractiveFromProject = 0x0002; - - // TODO: Remove pending https://github.com/dotnet/roslyn/issues/8927 . - public const int ExecuteInInteractiveWindow = 0x0010C; - - public const string CSharpInteractiveCommandSetIdString = "1492DB0A-85A2-4E43-BF0D-CE55B89A8CC6"; - public static readonly Guid CSharpInteractiveCommandSetId = new(CSharpInteractiveCommandSetIdString); - - public const string VisualBasicInteractiveCommandSetIdString = "93DF185E-D75B-4FDB-9D47-E90F111971C5"; - public static readonly Guid VisualBasicInteractiveCommandSetId = new(VisualBasicInteractiveCommandSetIdString); - } - } -} diff --git a/src/VisualStudio/Core/Def/Interactive/AbstractResetInteractiveCommand.cs b/src/VisualStudio/Core/Def/Interactive/AbstractResetInteractiveCommand.cs deleted file mode 100644 index e1496699080d2..0000000000000 --- a/src/VisualStudio/Core/Def/Interactive/AbstractResetInteractiveCommand.cs +++ /dev/null @@ -1,65 +0,0 @@ -// 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 disable - -using EnvDTE; -using Microsoft.VisualStudio.ComponentModelHost; -using Microsoft.VisualStudio.LanguageServices; -using Microsoft.VisualStudio.LanguageServices.Interactive; -using Microsoft.VisualStudio.Shell.Interop; -using System; - -namespace Roslyn.VisualStudio.Services.Interactive -{ - internal abstract class AbstractResetInteractiveCommand : IResetInteractiveCommand - { - private readonly VisualStudioWorkspace _workspace; - private readonly IComponentModel _componentModel; - private readonly VsInteractiveWindowProvider _interactiveWindowProvider; - private readonly IServiceProvider _serviceProvider; - - protected abstract string LanguageName { get; } - protected abstract string CreateReference(string referenceName); - protected abstract string CreateImport(string namespaceName); - - public AbstractResetInteractiveCommand( - VisualStudioWorkspace workspace, - VsInteractiveWindowProvider interactiveWindowProvider, - IServiceProvider serviceProvider) - { - _workspace = workspace; - _interactiveWindowProvider = interactiveWindowProvider; - _serviceProvider = serviceProvider; - _componentModel = (IComponentModel)GetService(typeof(SComponentModel)); - } - - private object GetService(Type type) - => _serviceProvider.GetService(type); - - public void ExecuteResetInteractive() - { - var resetInteractive = new VsResetInteractive( - _workspace, - (DTE)GetService(typeof(SDTE)), - _componentModel, - (IVsMonitorSelection)GetService(typeof(SVsShellMonitorSelection)), - (IVsSolutionBuildManager)GetService(typeof(SVsSolutionBuildManager)), - CreateReference, - CreateImport); - - var vsInteractiveWindow = _interactiveWindowProvider.Open(instanceId: 0, focus: true); - - void focusWindow(object s, EventArgs e) - { - // We have to set focus to the Interactive Window *after* the wait indicator is dismissed. - vsInteractiveWindow.Show(focus: true); - resetInteractive.ExecutionCompleted -= focusWindow; - } - - resetInteractive.ExecuteAsync(vsInteractiveWindow.InteractiveWindow, LanguageName + " Interactive"); - resetInteractive.ExecutionCompleted += focusWindow; - } - } -} diff --git a/src/VisualStudio/Core/Def/Interactive/AbstractResetInteractiveMenuCommand.cs b/src/VisualStudio/Core/Def/Interactive/AbstractResetInteractiveMenuCommand.cs deleted file mode 100644 index 8b473591e04a4..0000000000000 --- a/src/VisualStudio/Core/Def/Interactive/AbstractResetInteractiveMenuCommand.cs +++ /dev/null @@ -1,140 +0,0 @@ -// 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 disable - -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using Roslyn.VisualStudio.Services.Interactive; -using System; -using System.Linq; -using System.Runtime.InteropServices; -using System.Runtime.Versioning; -using System.ComponentModel.Design; -using Microsoft.VisualStudio.ComponentModelHost; -using Microsoft.CodeAnalysis.Editor; -using System.Threading; -using Task = System.Threading.Tasks.Task; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.Implementation.Interactive -{ - internal abstract class AbstractResetInteractiveMenuCommand - { - protected abstract string ProjectKind { get; } - - protected abstract CommandID GetResetInteractiveFromProjectCommandID(); - - private readonly OleMenuCommandService _menuCommandService; - private readonly IVsMonitorSelection _monitorSelection; - private readonly IComponentModel _componentModel; - private readonly IThreadingContext _threadingContext; - private readonly string _contentType; - - private readonly Lazy _resetInteractiveCommand; - - private Lazy ResetInteractiveCommand => _resetInteractiveCommand; - - public AbstractResetInteractiveMenuCommand( - string contentType, - OleMenuCommandService menuCommandService, - IVsMonitorSelection monitorSelection, - IComponentModel componentModel, - IThreadingContext threadingContext) - { - _contentType = contentType; - _menuCommandService = menuCommandService; - _monitorSelection = monitorSelection; - _componentModel = componentModel; - _threadingContext = threadingContext; - _resetInteractiveCommand = _componentModel.DefaultExportProvider - .GetExports() - .Where(resetInteractiveService => resetInteractiveService.Metadata.ContentTypes.Contains(_contentType)) - .SingleOrDefault(); - } - - internal async Task InitializeResetInteractiveFromProjectCommandAsync() - { - var resetInteractiveFromProjectCommand = new OleMenuCommand( - (sender, args) => - { - ResetInteractiveCommand.Value.ExecuteResetInteractive(); - }, - GetResetInteractiveFromProjectCommandID()); - - resetInteractiveFromProjectCommand.Supported = true; - - resetInteractiveFromProjectCommand.BeforeQueryStatus += (_, __) => - { - GetActiveProject(out var project, out var frameworkName); - var available = ResetInteractiveCommand != null - && project != null && project.Kind == ProjectKind - && frameworkName != null && frameworkName.Identifier == ".NETFramework"; - - resetInteractiveFromProjectCommand.Enabled = available; - resetInteractiveFromProjectCommand.Supported = available; - resetInteractiveFromProjectCommand.Visible = available; - }; - - await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); - _menuCommandService.AddCommand(resetInteractiveFromProjectCommand); - } - - private bool GetActiveProject(out EnvDTE.Project project, out FrameworkName frameworkName) - { - ThreadHelper.ThrowIfNotOnUIThread(); - - project = null; - frameworkName = null; - - var hierarchyPointer = IntPtr.Zero; - var selectionContainerPointer = IntPtr.Zero; - - try - { - Marshal.ThrowExceptionForHR( - _monitorSelection.GetCurrentSelection( - out hierarchyPointer, - out var itemid, - out var multiItemSelect, - out selectionContainerPointer)); - - if (itemid != (uint)VSConstants.VSITEMID.Root) - { - return false; - } - - if (Marshal.GetObjectForIUnknown(hierarchyPointer) is not IVsHierarchy hierarchy) - { - return false; - } - - Marshal.ThrowExceptionForHR( - hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ExtObject, out var extensibilityObject)); - Marshal.ThrowExceptionForHR( - hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID3.VSHPROPID_TargetFrameworkVersion, out var targetFrameworkVersion)); - Marshal.ThrowExceptionForHR( - hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID4.VSHPROPID_TargetFrameworkMoniker, out var targetFrameworkMonikerObject)); - - var targetFrameworkMoniker = targetFrameworkMonikerObject as string; - frameworkName = new System.Runtime.Versioning.FrameworkName(targetFrameworkMoniker); - - project = extensibilityObject as EnvDTE.Project; - return true; - } - finally - { - if (hierarchyPointer != IntPtr.Zero) - { - Marshal.Release(hierarchyPointer); - } - - if (selectionContainerPointer != IntPtr.Zero) - { - Marshal.Release(selectionContainerPointer); - } - } - } - } -} diff --git a/src/VisualStudio/Core/Def/Interactive/CSharpResetInteractiveMenuCommand.cs b/src/VisualStudio/Core/Def/Interactive/CSharpResetInteractiveMenuCommand.cs deleted file mode 100644 index 8e234096b1261..0000000000000 --- a/src/VisualStudio/Core/Def/Interactive/CSharpResetInteractiveMenuCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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 disable - -using Microsoft.CodeAnalysis.Editor; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.VisualStudio.ComponentModelHost; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using System.ComponentModel.Design; - -namespace Microsoft.VisualStudio.LanguageServices.Implementation.Interactive -{ - internal sealed class CSharpResetInteractiveMenuCommand - : AbstractResetInteractiveMenuCommand - { - public CSharpResetInteractiveMenuCommand( - OleMenuCommandService menuCommandService, - IVsMonitorSelection monitorSelection, - IComponentModel componentModel, - IThreadingContext threadingContext) - : base(ContentTypeNames.CSharpContentType, menuCommandService, monitorSelection, componentModel, threadingContext) - { - } - - protected override string ProjectKind => VSLangProj.PrjKind.prjKindCSharpProject; - - protected override CommandID GetResetInteractiveFromProjectCommandID() - => new(ID.InteractiveCommands.CSharpInteractiveCommandSetId, ID.InteractiveCommands.ResetInteractiveFromProject); - } -} diff --git a/src/VisualStudio/Core/Def/Interactive/CommonVsUtils.cs b/src/VisualStudio/Core/Def/Interactive/CommonVsUtils.cs deleted file mode 100644 index 7fe305ad8770f..0000000000000 --- a/src/VisualStudio/Core/Def/Interactive/CommonVsUtils.cs +++ /dev/null @@ -1,80 +0,0 @@ -// 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 disable - -using Microsoft.VisualStudio.ComponentModelHost; -using Microsoft.VisualStudio.Editor; -using Microsoft.VisualStudio.Shell.Interop; -using Microsoft.VisualStudio.Text; -using Microsoft.VisualStudio.Text.Editor; -using Microsoft.VisualStudio.TextManager.Interop; - -namespace Microsoft.VisualStudio.LanguageServices.Interactive -{ - // TODO (tomat): this needs to be polished and tested - internal static class CommonVsUtils - { - internal const string OutputWindowId = "34e76e81-ee4a-11d0-ae2e-00a0c90fffc3"; - - internal static string GetFilePath(ITextBuffer textBuffer) - { - if (textBuffer.Properties.TryGetProperty(typeof(ITextDocument), out var textDocument)) - { - return textDocument.FilePath; - } - else - { - return null; - } - } - - /// - /// Gets the current IWpfTextView that is the active document. - /// - /// - public static IWpfTextView GetActiveTextView() - { - var monitorSelection = (IVsMonitorSelection)Shell.Package.GetGlobalService(typeof(SVsShellMonitorSelection)); - if (monitorSelection == null) - { - return null; - } - - if (ErrorHandler.Failed(monitorSelection.GetCurrentElementValue((uint)VSConstants.VSSELELEMID.SEID_DocumentFrame, out var curDocument))) - { - // TODO: Report error - return null; - } - - if (curDocument is not IVsWindowFrame frame) - { - // TODO: Report error - return null; - } - - if (ErrorHandler.Failed(frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out var docView))) - { - // TODO: Report error - return null; - } - - if (docView is IVsCodeWindow) - { - if (ErrorHandler.Failed(((IVsCodeWindow)docView).GetPrimaryView(out var textView))) - { - // TODO: Report error - return null; - } - - var model = (IComponentModel)Shell.Package.GetGlobalService(typeof(SComponentModel)); - var adapterFactory = model.GetService(); - var wpfTextView = adapterFactory.GetWpfTextView(textView); - return wpfTextView; - } - - return null; - } - } -} diff --git a/src/VisualStudio/Core/Def/Interactive/VisualBasicResetInteractiveMenuCommand.cs b/src/VisualStudio/Core/Def/Interactive/VisualBasicResetInteractiveMenuCommand.cs deleted file mode 100644 index ae8209881fb7d..0000000000000 --- a/src/VisualStudio/Core/Def/Interactive/VisualBasicResetInteractiveMenuCommand.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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 disable - -using System.ComponentModel.Design; -using Microsoft.CodeAnalysis.Editor; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.VisualStudio.ComponentModelHost; -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; - -namespace Microsoft.VisualStudio.LanguageServices.Implementation.Interactive -{ - internal sealed class VisualBasicResetInteractiveMenuCommand - : AbstractResetInteractiveMenuCommand - { - public VisualBasicResetInteractiveMenuCommand( - OleMenuCommandService menuCommandService, - IVsMonitorSelection monitorSelection, - IComponentModel componentModel, - IThreadingContext threadingContext) - : base(ContentTypeNames.VisualBasicContentType, menuCommandService, monitorSelection, componentModel, threadingContext) - { - } - - protected override string ProjectKind => VSLangProj.PrjKind.prjKindVBProject; - - protected override CommandID GetResetInteractiveFromProjectCommandID() - => new(ID.InteractiveCommands.VisualBasicInteractiveCommandSetId, ID.InteractiveCommands.ResetInteractiveFromProject); - } -} diff --git a/src/VisualStudio/Core/Def/Interactive/VsInteractiveWindowPackage.cs b/src/VisualStudio/Core/Def/Interactive/VsInteractiveWindowPackage.cs index 5fa530dc15351..d85d5b81f926e 100644 --- a/src/VisualStudio/Core/Def/Interactive/VsInteractiveWindowPackage.cs +++ b/src/VisualStudio/Core/Def/Interactive/VsInteractiveWindowPackage.cs @@ -27,7 +27,9 @@ namespace Microsoft.VisualStudio.LanguageServices.Interactive internal abstract partial class VsInteractiveWindowPackage : AsyncPackage, IVsToolWindowFactory where TVsInteractiveWindowProvider : VsInteractiveWindowProvider { - protected abstract void InitializeMenuCommands(OleMenuCommandService menuCommandService); + protected virtual void InitializeMenuCommands(OleMenuCommandService menuCommandService) + { + } protected abstract Guid LanguageServiceGuid { get; } protected abstract Guid ToolWindowId { get; } diff --git a/src/VisualStudio/Core/Def/Interactive/VsResetInteractive.cs b/src/VisualStudio/Core/Def/Interactive/VsResetInteractive.cs index 1c1caeba5f9e1..7c58a2f8d93eb 100644 --- a/src/VisualStudio/Core/Def/Interactive/VsResetInteractive.cs +++ b/src/VisualStudio/Core/Def/Interactive/VsResetInteractive.cs @@ -30,27 +30,29 @@ namespace Microsoft.VisualStudio.LanguageServices.Interactive { + // TODO: convert to MEF component internal sealed class VsResetInteractive : ResetInteractive { private readonly VisualStudioWorkspace _workspace; private readonly EnvDTE.DTE _dte; - private readonly IComponentModel _componentModel; + private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor; private readonly IVsMonitorSelection _monitorSelection; private readonly IVsSolutionBuildManager _buildManager; internal VsResetInteractive( VisualStudioWorkspace workspace, EnvDTE.DTE dte, - IComponentModel componentModel, + EditorOptionsService editorOptionsService, + IUIThreadOperationExecutor uiThreadOperationExecutor, IVsMonitorSelection monitorSelection, IVsSolutionBuildManager buildManager, Func createReference, Func createImport) - : base(componentModel.GetService(), createReference, createImport) + : base(editorOptionsService, createReference, createImport) { _workspace = workspace; _dte = dte; - _componentModel = componentModel; + _uiThreadOperationExecutor = uiThreadOperationExecutor; _monitorSelection = monitorSelection; _buildManager = buildManager; } @@ -298,7 +300,7 @@ protected override void CancelBuildProject() => _dte.ExecuteCommand("Build.Cancel"); protected override IUIThreadOperationExecutor GetUIThreadOperationExecutor() - => _componentModel.GetService(); + => _uiThreadOperationExecutor; /// /// Return namespaces that can be resolved in the latest interactive compilation. diff --git a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs index 9e53c38bda7c2..5b9771b30f53b 100644 --- a/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs +++ b/src/VisualStudio/Core/Def/Library/ObjectBrowser/AbstractObjectBrowserLibraryManager.cs @@ -378,7 +378,7 @@ protected override int CreateNavInfo(SYMBOL_DESCRIPTION_NODE[] rgSymbolNodes, ui case (uint)_LIB_LISTTYPE.LLT_NAMESPACES: if (namespaceName.Length > 0) { - namespaceName.Append("."); + namespaceName.Append('.'); } namespaceName.Append(rgSymbolNodes[count].pszName); @@ -387,7 +387,7 @@ protected override int CreateNavInfo(SYMBOL_DESCRIPTION_NODE[] rgSymbolNodes, ui case (uint)_LIB_LISTTYPE.LLT_CLASSES: if (className.Length > 0) { - className.Append("."); + className.Append('.'); } className.Append(rgSymbolNodes[count].pszName); diff --git a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs index 4d4b89144398a..bb41ae499f85c 100644 --- a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs +++ b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs @@ -286,7 +286,6 @@ public bool TryFetch(LocalUserRegistryOptionPersister persister, OptionKey2 opti {"dotnet_extract_method_no_ref_or_out_structs", new RoamingProfileStorage("TextEditor.%LANGUAGE%.Specific.Don't Put Out Or Ref On Strcut")}, {"dotnet_fade_out_unreachable_code", new RoamingProfileStorage("TextEditor.%LANGUAGE%.Specific.FadeOutUnreachableCode")}, {"dotnet_fade_out_unused_imports", new RoamingProfileStorage("TextEditor.%LANGUAGE%.Specific.FadeOutUnusedImports")}, - {"dotnet_storage_cloud_cache", new FeatureFlagStorage(@"Roslyn.CloudCache3")}, {"dotnet_storage_database", new LocalUserProfileStorage(@"Roslyn\Internal\OnOff\Features", "Database")}, {"dotnet_add_imports_on_paste", new RoamingProfileStorage("TextEditor.%LANGUAGE%.Specific.AddImportsOnPaste2")}, {"dotnet_always_use_default_symbol_servers", new RoamingProfileStorage("TextEditor.AlwaysUseDefaultSymbolServers")}, diff --git a/src/VisualStudio/Core/Def/Progression/GraphBuilder.cs b/src/VisualStudio/Core/Def/Progression/GraphBuilder.cs index 2b343d00754a4..8362b094fa0d0 100644 --- a/src/VisualStudio/Core/Def/Progression/GraphBuilder.cs +++ b/src/VisualStudio/Core/Def/Progression/GraphBuilder.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.NavigateTo; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -76,22 +77,33 @@ private void PopulateMapsForFileInputNode(GraphNode inputNode, CancellationToken return; } - var project = _solution.Projects.FirstOrDefault( - p => string.Equals(p.FilePath, projectPath.OriginalString, StringComparison.OrdinalIgnoreCase)); - if (project == null) + var docIdsWithPath = _solution.GetDocumentIdsWithFilePath(filePath.OriginalString); + Document? document = null; + Project? project = null; + + foreach (var docIdWithPath in docIdsWithPath) { - return; - } + var projectState = _solution.GetProjectState(docIdWithPath.ProjectId); + if (projectState == null) + { + FatalError.ReportAndCatch(new Exception("GetDocumentIdsWithFilePath returned a document in a project that does not exist.")); + continue; + } - _nodeToContextProjectMap.Add(inputNode, project); + if (string.Equals(projectState.FilePath, projectPath.OriginalString)) + { + project = _solution.GetRequiredProject(projectState.Id); + document = project.GetDocument(docIdWithPath); + break; + } + } - var document = project.Documents.FirstOrDefault( - d => string.Equals(d.FilePath, filePath.OriginalString, StringComparison.OrdinalIgnoreCase)); - if (document == null) + if (document == null || project == null) { return; } + _nodeToContextProjectMap.Add(inputNode, project); _nodeToContextDocumentMap.Add(inputNode, document); } } @@ -353,9 +365,9 @@ private static void UpdateLabelsForNode(ISymbol symbol, Solution solution, Graph // This property will be used for drag-and-drop case. var commonLabel = new System.Text.StringBuilder(); commonLabel.Append(typeSymbol.Name); - commonLabel.Append("<"); + commonLabel.Append('<'); commonLabel.Append(string.Join(", ", typeSymbol.TypeParameters.Select(t => t.Name))); - commonLabel.Append(">"); + commonLabel.Append('>'); node[Microsoft.VisualStudio.ArchitectureTools.ProgressiveReveal.ProgressiveRevealSchema.CommonLabel] = commonLabel.ToString(); return; diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs index d8b5eeb3a32ae..f10baa7862802 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs @@ -7,16 +7,17 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Implementation.Suggestions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Workspaces.ProjectSystem; using Microsoft.VisualStudio.ComponentModelHost; +using Microsoft.VisualStudio.Editor; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Text; @@ -109,18 +110,6 @@ private void TryOpeningDocumentsForMonikerAndSetContextOnUIThread(string moniker }); } - private async Task TryOpeningDocumentsForMonikerAndSetContextOnUIThreadAsync(string moniker, ITextBuffer textBuffer, IVsHierarchy? hierarchy, CancellationToken cancellationToken) - { - await _projectSystemProjectFactory.ApplyChangeToWorkspaceAsync(async w => - { - await _foregroundAffinitization.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); - if (TryOpeningDocumentsForFilePathCore(w, moniker, textBuffer, hierarchy)) - { - EnsureSuggestedActionsSourceProviderEnabled(); - } - }, cancellationToken).ConfigureAwait(true); - } - private void EnsureSuggestedActionsSourceProviderEnabled() { _foregroundAffinitization.AssertIsForeground(); @@ -405,15 +394,15 @@ private async Task UpdateContextAfterOpenAsync(string filePath) EnsureSuggestedActionsSourceProviderEnabled(); } - internal async Task CheckForOpenFilesThatWeMissedAsync(CancellationToken cancellationToken) + internal void CheckForOpenFilesThatWeMissed() { // It's possible that Roslyn is loading asynchronously after documents were already opened by the user; this is a one-time check for // any of those -- after this point, we are subscribed to events so we'll know of anything else. - await _foregroundAffinitization.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + _foregroundAffinitization.AssertIsForeground(); foreach (var (filePath, textBuffer, hierarchy) in _openTextBufferProvider.EnumerateDocumentSet()) { - await TryOpeningDocumentsForMonikerAndSetContextOnUIThreadAsync(filePath, textBuffer, hierarchy, cancellationToken).ConfigureAwait(true); + TryOpeningDocumentsForMonikerAndSetContextOnUIThread(filePath, textBuffer, hierarchy); } } diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs index 17eb5576bfda4..8540fe9bd52c1 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -216,9 +216,11 @@ public async Task InitializeUIAffinitizedServicesAsync(IAsyncServiceProvider asy _memoryListener = memoryListener; } + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(_threadingContext.DisposalToken); + // This must be called after the _openFileTracker was assigned; this way we know that a file added from the project system either got checked // in CheckForAddedFileBeingOpenMaybeAsync, or we catch it here. - await openFileTracker.CheckForOpenFilesThatWeMissedAsync(_threadingContext.DisposalToken).ConfigureAwait(false); + openFileTracker.CheckForOpenFilesThatWeMissed(); // Switch to a background thread to avoid loading option providers on UI thread (telemetry is reading options). await TaskScheduler.Default; diff --git a/src/VisualStudio/Core/Def/RoslynPackage.cs b/src/VisualStudio/Core/Def/RoslynPackage.cs index 1da2f8570da89..3dd44fe8b03b7 100644 --- a/src/VisualStudio/Core/Def/RoslynPackage.cs +++ b/src/VisualStudio/Core/Def/RoslynPackage.cs @@ -23,7 +23,6 @@ using Microsoft.VisualStudio.LanguageServices.EditorConfigSettings; using Microsoft.VisualStudio.LanguageServices.Implementation; using Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics; -using Microsoft.VisualStudio.LanguageServices.Implementation.Interactive; using Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem; using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.RuleSets; @@ -267,35 +266,12 @@ private async Task LoadComponentsBackgroundAsync(CancellationToken cancellationT { await TaskScheduler.Default; - await LoadInteractiveMenusAsync(cancellationToken).ConfigureAwait(true); await LoadStackTraceExplorerMenusAsync(cancellationToken).ConfigureAwait(true); // Initialize keybinding reset detector await ComponentModel.DefaultExportProvider.GetExportedValue().InitializeAsync().ConfigureAwait(true); } - private async Task LoadInteractiveMenusAsync(CancellationToken cancellationToken) - { - // Obtain services and QueryInterface from the main thread - await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); - - var menuCommandService = (OleMenuCommandService)await GetServiceAsync(typeof(IMenuCommandService)).ConfigureAwait(true); - var monitorSelectionService = (IVsMonitorSelection)await GetServiceAsync(typeof(SVsShellMonitorSelection)).ConfigureAwait(true); - - // Switch to the background object for constructing commands - await TaskScheduler.Default; - - var threadingContext = ComponentModel.GetService(); - - await new CSharpResetInteractiveMenuCommand(menuCommandService, monitorSelectionService, ComponentModel, threadingContext) - .InitializeResetInteractiveFromProjectCommandAsync() - .ConfigureAwait(true); - - await new VisualBasicResetInteractiveMenuCommand(menuCommandService, monitorSelectionService, ComponentModel, threadingContext) - .InitializeResetInteractiveFromProjectCommandAsync() - .ConfigureAwait(true); - } - private async Task LoadStackTraceExplorerMenusAsync(CancellationToken cancellationToken) { // Obtain services and QueryInterface from the main thread diff --git a/src/VisualStudio/Core/Def/Storage/AbstractCloudCachePersistentStorageService.cs b/src/VisualStudio/Core/Def/Storage/AbstractCloudCachePersistentStorageService.cs deleted file mode 100644 index 31854a1866153..0000000000000 --- a/src/VisualStudio/Core/Def/Storage/AbstractCloudCachePersistentStorageService.cs +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Shared.Utilities; -using Microsoft.CodeAnalysis.Storage; -using Microsoft.CodeAnalysis.Storage.CloudCache; -using Microsoft.VisualStudio.RpcContracts.Caching; -using Roslyn.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.Storage -{ - internal abstract class AbstractCloudCachePersistentStorageService : AbstractPersistentStorageService, ICloudCacheStorageService - { - private const string StorageExtension = "CloudCache"; - - protected AbstractCloudCachePersistentStorageService(IPersistentStorageConfiguration configuration) - : base(configuration) - { - } - - protected abstract ValueTask CreateCacheServiceAsync(string solutionFolder, CancellationToken cancellationToken); - - protected sealed override string GetDatabaseFilePath(string workingFolderPath) - { - Contract.ThrowIfTrue(string.IsNullOrWhiteSpace(workingFolderPath)); - return Path.Combine(workingFolderPath, StorageExtension); - } - - protected sealed override bool ShouldDeleteDatabase(Exception exception) - { - // CloudCache owns the db, so we don't have to delete anything ourselves. - return false; - } - - protected sealed override async ValueTask TryOpenDatabaseAsync( - SolutionKey solutionKey, string workingFolderPath, string databaseFilePath, CancellationToken cancellationToken) - { - var solutionFolder = IOUtilities.PerformIO(() => Path.GetDirectoryName(solutionKey.FilePath)); - if (RoslynString.IsNullOrEmpty(solutionFolder)) - return null; - - var cacheService = await this.CreateCacheServiceAsync(solutionFolder, cancellationToken).ConfigureAwait(false); - var relativePathBase = await cacheService.GetRelativePathBaseAsync(cancellationToken).ConfigureAwait(false); - if (string.IsNullOrEmpty(relativePathBase)) - return null; - - return new CloudCachePersistentStorage(cacheService, solutionKey, workingFolderPath, relativePathBase, databaseFilePath); - } - } -} diff --git a/src/VisualStudio/Core/Def/Storage/CloudCachePersistentStorage.cs b/src/VisualStudio/Core/Def/Storage/CloudCachePersistentStorage.cs deleted file mode 100644 index 7af19df42a23c..0000000000000 --- a/src/VisualStudio/Core/Def/Storage/CloudCachePersistentStorage.cs +++ /dev/null @@ -1,193 +0,0 @@ -// 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. - -using System; -using System.IO; -using System.IO.Pipelines; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.PooledObjects; -using Microsoft.CodeAnalysis.Storage; -using Microsoft.VisualStudio.RpcContracts.Caching; -using Nerdbank.Streams; -using Roslyn.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.Storage -{ - /// - /// Implementation of Roslyn's sitting on top of the platform's cloud storage - /// system. - /// - internal class CloudCachePersistentStorage : AbstractPersistentStorage - { - private static readonly ObjectPool s_byteArrayPool = new(() => new byte[Checksum.HashSize]); - - /// - /// We do not need to store anything specific about the solution in this key as the platform cloud cache is - /// already keyed to the current solution. So this just allows us to store values considering that as the root. - /// - private static readonly CacheContainerKey s_solutionKey = new("Roslyn.Solution"); - - /// - /// Cache from project green nodes to the container keys we've computed for it (and the documents inside of it). - /// We can avoid computing these container keys when called repeatedly for the same projects/documents. - /// - private static readonly ConditionalWeakTable s_projectToContainerKeyCache = new(); - private readonly ConditionalWeakTable.CreateValueCallback _projectToContainerKeyCacheCallback; - - /// - /// Underlying cache service (owned by platform team) responsible for actual storage and retrieval of data. - /// - private readonly ICacheService _cacheService; - - public CloudCachePersistentStorage( - ICacheService cacheService, - SolutionKey solutionKey, - string workingFolderPath, - string relativePathBase, - string databaseFilePath) - : base(workingFolderPath, relativePathBase, databaseFilePath) - { - _cacheService = cacheService; - _projectToContainerKeyCacheCallback = ps => new ProjectContainerKeyCache(relativePathBase, ProjectKey.ToProjectKey(solutionKey, ps)); - } - - public sealed override void Dispose() - => (_cacheService as IDisposable)?.Dispose(); - - public sealed override ValueTask DisposeAsync() - { - Dispose(); - return ValueTaskFactory.CompletedTask; - } - - /// - /// Maps our own roslyn key to the appropriate key to use for the cloud cache system. To avoid lots of - /// allocations we cache these (weakly) so if the same keys are used we can use the same platform keys. - /// - private CacheContainerKey? GetContainerKey(ProjectKey projectKey, Project? project) - { - return project != null - ? s_projectToContainerKeyCache.GetValue(project.State, _projectToContainerKeyCacheCallback).ProjectContainerKey - : ProjectContainerKeyCache.CreateProjectContainerKey(this.SolutionFilePath, projectKey); - } - - /// - /// Maps our own roslyn key to the appropriate key to use for the cloud cache system. To avoid lots of - /// allocations we cache these (weakly) so if the same keys are used we can use the same platform keys. - /// - private CacheContainerKey? GetContainerKey( - DocumentKey documentKey, Document? document) - { - return document != null - ? s_projectToContainerKeyCache.GetValue(document.Project.State, _projectToContainerKeyCacheCallback).GetDocumentContainerKey(document.State) - : ProjectContainerKeyCache.CreateDocumentContainerKey(this.SolutionFilePath, documentKey); - } - - public sealed override Task ChecksumMatchesAsync(string name, Checksum checksum, CancellationToken cancellationToken) - => ChecksumMatchesAsync(name, checksum, s_solutionKey, cancellationToken); - - protected sealed override Task ChecksumMatchesAsync(ProjectKey projectKey, Project? project, string name, Checksum checksum, CancellationToken cancellationToken) - => ChecksumMatchesAsync(name, checksum, GetContainerKey(projectKey, project), cancellationToken); - - protected sealed override Task ChecksumMatchesAsync(DocumentKey documentKey, Document? document, string name, Checksum checksum, CancellationToken cancellationToken) - => ChecksumMatchesAsync(name, checksum, GetContainerKey(documentKey, document), cancellationToken); - - private async Task ChecksumMatchesAsync(string name, Checksum checksum, CacheContainerKey? containerKey, CancellationToken cancellationToken) - { - // If we failed to get a container key (for example, because the client is referencing a file not under the - // solution folder) then we can't proceed. - if (containerKey == null) - return false; - - using var bytes = s_byteArrayPool.GetPooledObject(); - checksum.WriteTo(bytes.Object); - - return await _cacheService.CheckExistsAsync(new CacheItemKey(containerKey.Value, name) { Version = bytes.Object }, cancellationToken).ConfigureAwait(false); - } - - public sealed override Task ReadStreamAsync(string name, Checksum? checksum, CancellationToken cancellationToken) - => ReadStreamAsync(name, checksum, s_solutionKey, cancellationToken); - - protected sealed override Task ReadStreamAsync(ProjectKey projectKey, Project? project, string name, Checksum? checksum, CancellationToken cancellationToken) - => ReadStreamAsync(name, checksum, GetContainerKey(projectKey, project), cancellationToken); - - protected sealed override Task ReadStreamAsync(DocumentKey documentKey, Document? document, string name, Checksum? checksum, CancellationToken cancellationToken) - => ReadStreamAsync(name, checksum, GetContainerKey(documentKey, document), cancellationToken); - - private async Task ReadStreamAsync(string name, Checksum? checksum, CacheContainerKey? containerKey, CancellationToken cancellationToken) - { - // If we failed to get a container key (for example, because the client is referencing a file not under the - // solution folder) then we can't proceed. - if (containerKey == null) - return null; - - if (checksum == null) - { - return await ReadStreamAsync(new CacheItemKey(containerKey.Value, name), cancellationToken).ConfigureAwait(false); - } - else - { - using var bytes = s_byteArrayPool.GetPooledObject(); - checksum.Value.WriteTo(bytes.Object); - - return await ReadStreamAsync(new CacheItemKey(containerKey.Value, name) { Version = bytes.Object }, cancellationToken).ConfigureAwait(false); - } - } - - private async Task ReadStreamAsync(CacheItemKey key, CancellationToken cancellationToken) - { - var pipe = new Pipe(); - var result = await _cacheService.TryGetItemAsync(key, pipe.Writer, cancellationToken).ConfigureAwait(false); - if (!result) - return null; - - // Clients will end up doing blocking reads on the synchronous stream we return from this. This can - // negatively impact our calls as that will cause sync blocking on the async work to fill the pipe. To - // alleviate that issue, we actually asynchronously read in the entire stream into memory inside the reader - // and then pass that out. This should not be a problem in practice as PipeReader internally intelligently - // uses and pools reasonable sized buffers, preventing us from exacerbating the GC or causing LOH - // allocations. - return await pipe.Reader.AsPrebufferedStreamAsync(cancellationToken).ConfigureAwait(false); - } - - public sealed override Task WriteStreamAsync(string name, Stream stream, Checksum? checksum, CancellationToken cancellationToken) - => WriteStreamAsync(name, stream, checksum, s_solutionKey, cancellationToken); - - protected sealed override Task WriteStreamAsync(ProjectKey projectKey, Project? project, string name, Stream stream, Checksum? checksum, CancellationToken cancellationToken) - => WriteStreamAsync(name, stream, checksum, GetContainerKey(projectKey, project), cancellationToken); - - protected sealed override Task WriteStreamAsync(DocumentKey documentKey, Document? document, string name, Stream stream, Checksum? checksum, CancellationToken cancellationToken) - => WriteStreamAsync(name, stream, checksum, GetContainerKey(documentKey, document), cancellationToken); - - private async Task WriteStreamAsync(string name, Stream stream, Checksum? checksum, CacheContainerKey? containerKey, CancellationToken cancellationToken) - { - // If we failed to get a container key (for example, because the client is referencing a file not under the - // solution folder) then we can't proceed. - if (containerKey == null) - return false; - - if (checksum == null) - { - return await WriteStreamAsync(new CacheItemKey(containerKey.Value, name), stream, cancellationToken).ConfigureAwait(false); - } - else - { - using var bytes = s_byteArrayPool.GetPooledObject(); - checksum.Value.WriteTo(bytes.Object); - - return await WriteStreamAsync(new CacheItemKey(containerKey.Value, name) { Version = bytes.Object }, stream, cancellationToken).ConfigureAwait(false); - } - } - - private async Task WriteStreamAsync(CacheItemKey key, Stream stream, CancellationToken cancellationToken) - { - await _cacheService.SetItemAsync(key, PipeReader.Create(stream), shareable: false, cancellationToken).ConfigureAwait(false); - return true; - } - } -} diff --git a/src/VisualStudio/Core/Def/Storage/ProjectContainerKeyCache.cs b/src/VisualStudio/Core/Def/Storage/ProjectContainerKeyCache.cs deleted file mode 100644 index 6cfd3d98c1c60..0000000000000 --- a/src/VisualStudio/Core/Def/Storage/ProjectContainerKeyCache.cs +++ /dev/null @@ -1,110 +0,0 @@ -// 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. - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Runtime.CompilerServices; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Storage; -using Microsoft.VisualStudio.RpcContracts.Caching; -using Roslyn.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.Storage -{ - /// - /// Cache of our own internal roslyn storage keys to the equivalent platform cloud cache keys. Cloud cache keys can - /// store a lot of date in them (like their 'dimensions' dictionary. We don't want to continually recreate these as - /// we read/write date to the db. - /// - internal class ProjectContainerKeyCache - { - private static readonly ImmutableSortedDictionary EmptyDimensions = ImmutableSortedDictionary.Create(StringComparer.Ordinal); - - /// - /// Container key explicitly for the project itself. - /// - public readonly CacheContainerKey? ProjectContainerKey; - - /// - /// Cache from document green nodes to the container keys we've computed for it. We can avoid computing these - /// container keys when called repeatedly for the same documents. - /// - /// - /// We can use a normal Dictionary here instead of a as - /// instances of are always owned in a context where the is alive. As that instance is alive, all s the project - /// points at will be held alive strongly too. - /// - private readonly Dictionary _documentToContainerKey = new(); - private readonly Func _documentToContainerKeyCallback; - - public ProjectContainerKeyCache(string relativePathBase, ProjectKey projectKey) - { - ProjectContainerKey = CreateProjectContainerKey(relativePathBase, projectKey); - - _documentToContainerKeyCallback = ds => CreateDocumentContainerKey(relativePathBase, DocumentKey.ToDocumentKey(projectKey, ds)); - } - - public CacheContainerKey? GetDocumentContainerKey(TextDocumentState state) - { - lock (_documentToContainerKey) - return _documentToContainerKey.GetOrAdd(state, _documentToContainerKeyCallback); - } - - public static CacheContainerKey? CreateProjectContainerKey( - string relativePathBase, ProjectKey projectKey) - { - // Creates a container key for this project. The container key is a mix of the project's name, relative - // file path (to the solution), and optional parse options. - - // If we don't have a valid solution path, we can't store anything. - if (string.IsNullOrEmpty(relativePathBase)) - return null; - - // We have to have a file path for this project - if (RoslynString.IsNullOrEmpty(projectKey.FilePath)) - return null; - - // The file path has to be relative to the base path the DB is associated with (either the solution-path or - // repo-path). - var relativePath = PathUtilities.GetRelativePath(relativePathBase, projectKey.FilePath!); - if (relativePath == projectKey.FilePath) - return null; - - var dimensions = EmptyDimensions - .Add($"{nameof(ProjectKey)}.{nameof(ProjectKey.Name)}", projectKey.Name) - .Add($"{nameof(ProjectKey)}.{nameof(ProjectKey.FilePath)}", relativePath) - .Add($"{nameof(ProjectKey)}.{nameof(ProjectKey.ParseOptionsChecksum)}", projectKey.ParseOptionsChecksum.ToString()); - - return new CacheContainerKey("Roslyn.Project", dimensions); - } - - public static CacheContainerKey? CreateDocumentContainerKey( - string relativePathBase, - DocumentKey documentKey) - { - // See if we can get a project key for this info. If not, we def can't get a doc key. - var projectContainerKey = CreateProjectContainerKey(relativePathBase, documentKey.Project); - if (projectContainerKey == null) - return null; - - // We have to have a file path for this document - if (string.IsNullOrEmpty(documentKey.FilePath)) - return null; - - // The file path has to be relative to the base path the DB is associated with (either the solution-path or - // repo-path). - var relativePath = PathUtilities.GetRelativePath(relativePathBase, documentKey.FilePath!); - if (relativePath == documentKey.FilePath) - return null; - - var dimensions = projectContainerKey.Value.Dimensions - .Add($"{nameof(DocumentKey)}.{nameof(DocumentKey.Name)}", documentKey.Name) - .Add($"{nameof(DocumentKey)}.{nameof(DocumentKey.FilePath)}", relativePath); - - return new CacheContainerKey("Roslyn.Document", dimensions); - } - } -} diff --git a/src/VisualStudio/Core/Def/Storage/VisualStudioCloudCacheStorageService.cs b/src/VisualStudio/Core/Def/Storage/VisualStudioCloudCacheStorageService.cs deleted file mode 100644 index ead75b0670bfb..0000000000000 --- a/src/VisualStudio/Core/Def/Storage/VisualStudioCloudCacheStorageService.cs +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -using System; -using System.Collections.Immutable; -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Storage.CloudCache; -using Microsoft.ServiceHub.Framework; -using Microsoft.VisualStudio.RpcContracts.Caching; -using Microsoft.VisualStudio.Shell.ServiceBroker; -using Roslyn.Utilities; - -namespace Microsoft.VisualStudio.LanguageServices.Storage -{ - internal class VisualStudioCloudCacheStorageService : AbstractCloudCachePersistentStorageService - { - [ExportWorkspaceServiceFactory(typeof(ICloudCacheStorageService), ServiceLayer.Host), Shared] - internal class ServiceFactory : IWorkspaceServiceFactory - { - private readonly IVsService _brokeredServiceContainer; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ServiceFactory(IVsService brokeredServiceContainer) - { - _brokeredServiceContainer = brokeredServiceContainer; - } - - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - => new VisualStudioCloudCacheStorageService(_brokeredServiceContainer, workspaceServices.GetRequiredService()); - } - - private readonly IVsService _brokeredServiceContainer; - - public VisualStudioCloudCacheStorageService(IVsService brokeredServiceContainer, IPersistentStorageConfiguration configuration) - : base(configuration) - { - _brokeredServiceContainer = brokeredServiceContainer; - } - - protected sealed override async ValueTask CreateCacheServiceAsync(string solutionFolder, CancellationToken cancellationToken) - { - var serviceContainer = await _brokeredServiceContainer.GetValueAsync(cancellationToken).ConfigureAwait(false); - var serviceBroker = serviceContainer.GetFullAccessServiceBroker(); - -#pragma warning disable ISB001 // Dispose of proxies - // cache service will be disposed inside VisualStudioCloudCachePersistentStorage.Dispose - var cacheService = await serviceBroker.GetProxyAsync( - VisualStudioServices.VS2019_10.CacheService, - // replace with CacheService.RelativePathBaseActivationArgKey once available. - new ServiceActivationOptions { ActivationArguments = ImmutableDictionary.Empty.Add("RelativePathBase", solutionFolder) }, - cancellationToken).ConfigureAwait(false); -#pragma warning restore ISB001 // Dispose of proxies - - Contract.ThrowIfNull(cacheService); - return cacheService; - } - } -} diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index 25eea61499482..e75755542d9cd 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -249,7 +249,7 @@ Collapse local functions when collapsing to definitions - Collapse local functions when collapsing to definitions + Sbalit místní funkce při sbalení do definic @@ -1499,7 +1499,7 @@ 'System.Void' is not a valid type for a parameter - 'System.Void' není platný typ parametru. + System.Void není platný typ parametru {Locked="System.Void"} "System.Void" represents CLR's type and should not be localized diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index 83a7bc4b2a1f6..47f2a66f9850f 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -1104,7 +1104,7 @@ Prefer collection expression - Préférer l’expression collection + Préférer une expression de collection @@ -1499,7 +1499,7 @@ 'System.Void' is not a valid type for a parameter - 'System.Void' n’est pas un type valide pour un paramètre + « System.Void » n’est pas un type valide pour un paramètre {Locked="System.Void"} "System.Void" represents CLR's type and should not be localized diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index d785fbfc1b51a..d19b1c800b306 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -1499,7 +1499,7 @@ 'System.Void' is not a valid type for a parameter - 'System.Void' はパラメーターの有効な型ではありません + 'System.Void' はパラメーターとして有効な型ではありません {Locked="System.Void"} "System.Void" represents CLR's type and should not be localized diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index daa2fdb37e3a9..ccecee91c9fb1 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -1499,7 +1499,7 @@ 'System.Void' is not a valid type for a parameter - 'System.Void' nie jest prawidłowym typem dla parametru + Element „System.Void” nie jest prawidłowym typem parametru {Locked="System.Void"} "System.Void" represents CLR's type and should not be localized diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 1a09990dd4902..5d85f1dfe0ef9 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -1104,7 +1104,7 @@ Prefer collection expression - Preferir expressão de coleção + Preferir a expressão de coleção diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index 7e31ed3bb5abb..8ab8fef64aef9 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -249,7 +249,7 @@ Collapse local functions when collapsing to definitions - Collapse local functions when collapsing to definitions + Tanımlara daraltılırken yerel işlevleri daralt @@ -1104,7 +1104,7 @@ Prefer collection expression - Koleksiyon ifadesini tercih eder + Koleksiyon ifadesini tercih et diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index cca856e50b1ed..51b8a6812f03a 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -1104,7 +1104,7 @@ Prefer collection expression - 偏好集合運算式 + 慣用集合運算式 diff --git a/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProjectFactory.cs b/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProjectFactory.cs index 76414aff64932..769bee1f15345 100644 --- a/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProjectFactory.cs +++ b/src/VisualStudio/Core/Impl/ProjectSystem/CPS/CPSProjectFactory.cs @@ -227,7 +227,8 @@ public async Task CreateProjectContextAsync(Guid id, s throw new InvalidProjectDataException(itemName, values[0], $"Item group '{itemName}' is required to specify an absolute path or a path relative to the directory containing the project: '{values[0]}'."); } - return path; + // normalize "." and ".." on the way out + return FileUtilities.TryNormalizeAbsolutePath(path) ?? path; } } } diff --git a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs index 009222159a872..b4720a60d12de 100644 --- a/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs +++ b/src/VisualStudio/Core/Impl/SolutionExplorer/DiagnosticItem/CpsDiagnosticItemSourceProvider.cs @@ -43,11 +43,10 @@ public CpsDiagnosticItemSourceProvider( _workspace = workspace; } - protected override IAttachedCollectionSource? CreateCollectionSource(IVsHierarchyItem item, string relationshipName) + protected override IAttachedCollectionSource? CreateCollectionSource(IVsHierarchyItem? item, string relationshipName) { - if (item != null && - item.HierarchyIdentity != null && - item.HierarchyIdentity.NestedHierarchy != null && + if (item?.HierarchyIdentity?.NestedHierarchy != null && + !item.IsDisposed && relationshipName == KnownRelationships.Contains) { if (NestedHierarchyHasProjectTreeCapability(item, "AnalyzerDependency")) diff --git a/src/VisualStudio/Core/Test.Next/Remote/SerializationValidator.cs b/src/VisualStudio/Core/Test.Next/Remote/SerializationValidator.cs index 140b522bf657b..238fc60678419 100644 --- a/src/VisualStudio/Core/Test.Next/Remote/SerializationValidator.cs +++ b/src/VisualStudio/Core/Test.Next/Remote/SerializationValidator.cs @@ -98,11 +98,12 @@ public async Task GetValueAsync(Checksum checksum) stream.Position = 0; using var reader = ObjectReader.TryGetReader(stream); + Contract.ThrowIfNull(reader); // deserialize bits to object - var result = Serializer.Deserialize(data.Kind, reader, CancellationToken.None); + var result = Serializer.Deserialize(data.Kind, reader, CancellationToken.None); Contract.ThrowIfNull(result); - return result; + return (T)result; } public async Task GetSolutionAsync(SolutionAssetStorage.Scope scope) diff --git a/src/VisualStudio/Core/Test.Next/Remote/SnapshotSerializationTests.cs b/src/VisualStudio/Core/Test.Next/Remote/SnapshotSerializationTests.cs index f7580e83af6f8..c0758bc51aeb3 100644 --- a/src/VisualStudio/Core/Test.Next/Remote/SnapshotSerializationTests.cs +++ b/src/VisualStudio/Core/Test.Next/Remote/SnapshotSerializationTests.cs @@ -620,7 +620,7 @@ public void TestEncodingSerialization() using var objectReader = ObjectReader.TryGetReader(stream); - var newText = serializer.Deserialize(sourceText.GetWellKnownSynchronizationKind(), objectReader, CancellationToken.None); + var newText = (SourceText)serializer.Deserialize(sourceText.GetWellKnownSynchronizationKind(), objectReader, CancellationToken.None); Assert.Equal(sourceText.ToString(), newText.ToString()); } @@ -639,7 +639,7 @@ public void TestEncodingSerialization() using var objectReader = ObjectReader.TryGetReader(stream); - var newText = serializer.Deserialize(sourceText.GetWellKnownSynchronizationKind(), objectReader, CancellationToken.None); + var newText = (SourceText)serializer.Deserialize(sourceText.GetWellKnownSynchronizationKind(), objectReader, CancellationToken.None); Assert.Equal(sourceText.ToString(), newText.ToString()); } } @@ -668,7 +668,7 @@ void VerifyOptions(CompilationOptions originalOptions) stream.Position = 0; using var objectReader = ObjectReader.TryGetReader(stream); - var recoveredOptions = serializer.Deserialize(originalOptions.GetWellKnownSynchronizationKind(), objectReader, CancellationToken.None); + var recoveredOptions = (CompilationOptions)serializer.Deserialize(originalOptions.GetWellKnownSynchronizationKind(), objectReader, CancellationToken.None); var original = serializer.CreateChecksum(originalOptions, CancellationToken.None); var recovered = serializer.CreateChecksum(recoveredOptions, CancellationToken.None); @@ -689,7 +689,7 @@ private static SolutionAsset CloneAsset(ISerializerService serializer, SolutionA stream.Position = 0; using var reader = ObjectReader.TryGetReader(stream); - var recovered = serializer.Deserialize(asset.Kind, reader, CancellationToken.None); + var recovered = serializer.Deserialize(asset.Kind, reader, CancellationToken.None); var assetFromStorage = new SolutionAsset(serializer.CreateChecksum(recovered, CancellationToken.None), recovered); Assert.Equal(asset.Checksum, assetFromStorage.Checksum); diff --git a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs index 433c7063c8ce9..476859ccf6bd2 100644 --- a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs @@ -19,6 +19,7 @@ using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Remote.Testing; using Microsoft.CodeAnalysis.Serialization; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; @@ -530,21 +531,28 @@ public async Task TestPartialProjectSync_GetSolutionFirst() solution = project2.Solution; - var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); + var map = new Dictionary(); + var assetProvider = new AssetProvider( + Checksum.Create(ImmutableArray.CreateRange(Guid.NewGuid().ToByteArray())), new SolutionAssetCache(), new SimpleAssetSource(workspace.Services.GetService(), map), remoteWorkspace.Services.GetService()); + + // Do the initial full sync + await solution.AppendAssetMapAsync(map, CancellationToken.None); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); Assert.Equal(solutionChecksum, await syncedFullSolution.CompilationState.GetChecksumAsync(CancellationToken.None)); Assert.Equal(2, syncedFullSolution.Projects.Count()); // Syncing project1 should do nothing as syncing the solution already synced it over. var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); + await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); Assert.Equal(2, project1SyncedSolution.Projects.Count()); // Syncing project2 should do nothing as syncing the solution already synced it over. var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); + await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); Assert.Equal(2, project2SyncedSolution.Projects.Count()); } @@ -575,16 +583,16 @@ public async Task TestPartialProjectSync_GetSolutionLast() Assert.Equal(1, project1SyncedSolution.Projects.Count()); Assert.Equal(project1.Name, project1SyncedSolution.Projects.Single().Name); - // Syncing project 2 should end up with p1 and p2 synced over. + // Syncing project 2 should end up with only p2 synced over. await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(2, project2SyncedSolution.Projects.Count()); + Assert.Equal(1, project2SyncedSolution.Projects.Count()); - // then syncing the whole project should have no effect. + // then syncing the whole project should now copy both over. await solution.AppendAssetMapAsync(map, CancellationToken.None); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); Assert.Equal(solutionChecksum, await syncedFullSolution.CompilationState.GetChecksumAsync(CancellationToken.None)); Assert.Equal(2, syncedFullSolution.Projects.Count()); @@ -649,19 +657,19 @@ public async Task TestPartialProjectSync_GetDependentProjects2() var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); Assert.Equal(2, project3SyncedSolution.Projects.Count()); - // if we then sync just P2, we should still have P2 and P3 from the prior sync + // if we then sync just P2, we should still have only P2 in the synced cone await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(2, project2SyncedSolution.Projects.Count()); - AssertEx.SetEqual(new[] { project2.Name, project3.Name }, project2SyncedSolution.Projects.Select(p => p.Name)); + Assert.Equal(1, project2SyncedSolution.Projects.Count()); + AssertEx.Equal(project2.Name, project2SyncedSolution.Projects.Single().Name); - // if we then sync just P1, we should have 3 projects synved over now. + // if we then sync just P1, we should only have it in its own cone. await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(3, project1SyncedSolution.Projects.Count()); - AssertEx.SetEqual(new[] { project1.Name, project2.Name, project3.Name }, project1SyncedSolution.Projects.Select(p => p.Name)); + Assert.Equal(1, project1SyncedSolution.Projects.Count()); + AssertEx.Equal(project1.Name, project1SyncedSolution.Projects.Single().Name); } [Fact] @@ -691,15 +699,17 @@ public async Task TestPartialProjectSync_GetDependentProjects3() var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); Assert.Equal(3, project3SyncedSolution.Projects.Count()); - // syncing project2 should do nothing as everything is already synced + // syncing project2 should only have it and project 1. + await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(3, project2SyncedSolution.Projects.Count()); + Assert.Equal(2, project2SyncedSolution.Projects.Count()); - // syncing project1 should do nothing as everything is already synced + // syncing project1 should only be itself + await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(3, project1SyncedSolution.Projects.Count()); + Assert.Equal(1, project1SyncedSolution.Projects.Count()); } [Fact] @@ -729,15 +739,17 @@ public async Task TestPartialProjectSync_GetDependentProjects4() var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); Assert.Equal(3, project3SyncedSolution.Projects.Count()); - // Syncing project2 should do nothing as it's already synced + // Syncing project2 should only have a cone with itself. + await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(3, project2SyncedSolution.Projects.Count()); + Assert.Equal(1, project2SyncedSolution.Projects.Count()); - // Syncing project1 should do nothing as it's already synced + // Syncing project1 should only have a cone with itself. + await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(3, project1SyncedSolution.Projects.Count()); + Assert.Equal(1, project1SyncedSolution.Projects.Count()); } [Fact] @@ -766,11 +778,112 @@ public async Task TestPartialProjectSync_Options1() Assert.Equal(1, project1SyncedSolution.Projects.Count()); Assert.Equal(project1.Name, project1SyncedSolution.Projects.Single().Name); - // Syncing over project2 should now give two sets of options. + // Syncing over project2 should also only be one set of options. await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - Assert.Equal(2, project2SyncedSolution.Projects.Count()); + Assert.Equal(1, project2SyncedSolution.Projects.Count()); + } + + [Fact] + public async Task TestPartialProjectSync_DoesNotSeeChangesOutsideOfCone() + { + var code = @"class Test { void Method() { } }"; + + using var workspace = TestWorkspace.CreateCSharp(code); + using var remoteWorkspace = CreateRemoteWorkspace(); + + var solution = workspace.CurrentSolution; + + var project1 = solution.Projects.Single(); + var project2 = solution.AddProject("P2", "P2", LanguageNames.VisualBasic); + + solution = project2.Solution; + + var map = new Dictionary(); + var assetProvider = new AssetProvider( + Checksum.Create(ImmutableArray.CreateRange(Guid.NewGuid().ToByteArray())), new SolutionAssetCache(), new SimpleAssetSource(workspace.Services.GetService(), map), remoteWorkspace.Services.GetService()); + + // Do the initial full sync + await solution.AppendAssetMapAsync(map, CancellationToken.None); + var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); + var fullSyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); + Assert.Equal(2, fullSyncedSolution.Projects.Count()); + + // Mutate both projects to each have a document in it. + solution = solution.GetProject(project1.Id).AddDocument("X.cs", SourceText.From("// X")).Project.Solution; + solution = solution.GetProject(project2.Id).AddDocument("Y.vb", SourceText.From("' Y")).Project.Solution; + + // Now just sync project1's cone over. We should not see the change to project2 on the remote side. + // But we will still see project2. + { + await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); + var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + Assert.Equal(2, project1SyncedSolution.Projects.Count()); + var csharpProject = project1SyncedSolution.Projects.Single(p => p.Language == LanguageNames.CSharp); + var vbProject = project1SyncedSolution.Projects.Single(p => p.Language == LanguageNames.VisualBasic); + Assert.True(csharpProject.DocumentIds.Count == 2); + Assert.Empty(vbProject.DocumentIds); + } + + // Similarly, if we sync just project2's cone over: + { + await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); + var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + Assert.Equal(2, project2SyncedSolution.Projects.Count()); + var csharpProject = project2SyncedSolution.Projects.Single(p => p.Language == LanguageNames.CSharp); + var vbProject = project2SyncedSolution.Projects.Single(p => p.Language == LanguageNames.VisualBasic); + Assert.Single(csharpProject.DocumentIds); + Assert.Single(vbProject.DocumentIds); + } + } + + [Fact] + public async Task TestPartialProjectSync_AddP2PRef() + { + var code = @"class Test { void Method() { } }"; + + using var workspace = TestWorkspace.CreateCSharp(code); + using var remoteWorkspace = CreateRemoteWorkspace(); + + var solution = workspace.CurrentSolution; + + var project1 = solution.Projects.Single(); + var project2 = solution.AddProject("P2", "P2", LanguageNames.CSharp); + + solution = project2.Solution; + + var map = new Dictionary(); + var assetProvider = new AssetProvider( + Checksum.Create(ImmutableArray.CreateRange(Guid.NewGuid().ToByteArray())), new SolutionAssetCache(), new SimpleAssetSource(workspace.Services.GetService(), map), remoteWorkspace.Services.GetService()); + + // Do the initial full sync + await solution.AppendAssetMapAsync(map, CancellationToken.None); + var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); + var fullSyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); + Assert.Equal(2, fullSyncedSolution.Projects.Count()); + + // Mutate both projects to have a document in it, and add a p2p ref from project1 to project2 + solution = solution.GetProject(project1.Id).AddDocument("X.cs", SourceText.From("// X")).Project.Solution; + solution = solution.GetProject(project2.Id).AddDocument("Y.cs", SourceText.From("// Y")).Project.Solution; + solution = solution.GetProject(project1.Id).AddProjectReference(new ProjectReference(project2.Id)).Solution; + + // Now just sync project1's cone over. This will validate that the p2p ref doesn't try to add a new + // project, but instead sees the existing one. + { + await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); + var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + Assert.Equal(2, project1SyncedSolution.Projects.Count()); + var project1Synced = project1SyncedSolution.GetRequiredProject(project1.Id); + var project2Synced = project1SyncedSolution.GetRequiredProject(project2.Id); + + Assert.True(project1Synced.DocumentIds.Count == 2); + Assert.Single(project2Synced.DocumentIds); + Assert.Single(project1Synced.ProjectReferences); + } } [Fact] diff --git a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs index 6c5ce2adf2242..98402fe2b2216 100644 --- a/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs +++ b/src/VisualStudio/DevKit/Impl/Logging/VSCodeTelemetryLogger.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Telemetry; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.Telemetry; namespace Microsoft.CodeAnalysis.LanguageServer.Logging; @@ -26,13 +27,16 @@ internal sealed class VSCodeTelemetryLogger : ITelemetryReporter private const string CollectorApiKey = "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255"; private static int _dumpsSubmitted = 0; + private readonly ILogger _logger; + private static readonly ConcurrentDictionary _pendingScopes = new(concurrencyLevel: 2, capacity: 10); [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VSCodeTelemetryLogger(IAsynchronousOperationListenerProvider asyncListenerProvider) + public VSCodeTelemetryLogger(IAsynchronousOperationListenerProvider asyncListenerProvider, ILoggerFactory loggerFactory) { _asyncListenerProvider = asyncListenerProvider; + _logger = loggerFactory.CreateLogger(); } public void InitializeSession(string telemetryLevel, string? sessionId, bool isDefaultSession) @@ -50,6 +54,8 @@ public void InitializeSession(string telemetryLevel, string? sessionId, bool isD session.Start(); session.RegisterForReliabilityEvent(); + _logger.LogTrace("Telemetry session started with sessionID: {sessionId}", sessionId); + _telemetrySession = session; TelemetryLogger.Create(_telemetrySession, logDelta: false, _asyncListenerProvider); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingReference.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingReference.cs index 12401d332c583..b7a2edebb2413 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingReference.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpAddMissingReference.cs @@ -164,7 +164,7 @@ public async Task InvokeSomeFixesInCSharpThenVerifyReferences() await TestServices.Editor.PlaceCaretAsync("y.goo", charsOffset: 1, HangMitigatingCancellationToken); await TestServices.Editor.InvokeCodeActionListAsync(HangMitigatingCancellationToken); await TestServices.EditorVerifier.CodeActionAsync("Add reference to 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.", applyFix: true, cancellationToken: HangMitigatingCancellationToken); - await TestServices.SolutionExplorerVerifier.AssemblyReferencePresentAsync( + await TestServices.SolutionVerifier.AssemblyReferencePresentAsync( projectName: consoleProject, assemblyName: "System.Windows.Forms", assemblyVersion: "4.0.0.0", @@ -173,7 +173,7 @@ await TestServices.SolutionExplorerVerifier.AssemblyReferencePresentAsync( await TestServices.Editor.PlaceCaretAsync("a.bar", charsOffset: 1, HangMitigatingCancellationToken); await TestServices.Editor.InvokeCodeActionListAsync(HangMitigatingCancellationToken); await TestServices.EditorVerifier.CodeActionAsync("Add project reference to 'ClassLibrary3'.", applyFix: true, cancellationToken: HangMitigatingCancellationToken); - await TestServices.SolutionExplorerVerifier.ProjectReferencePresentAsync( + await TestServices.SolutionVerifier.ProjectReferencePresentAsync( projectName: consoleProject, referencedProjectName: ClassLibrary3Name, HangMitigatingCancellationToken); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToDefinition.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToDefinition.cs index 0289ba665c6eb..4d1439eaeebbb 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToDefinition.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToDefinition.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Structure; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.Shell.TableControl; +using Roslyn.Test.Utilities; using Roslyn.VisualStudio.IntegrationTests; using Roslyn.VisualStudio.IntegrationTests.InProcess; using Roslyn.VisualStudio.NewIntegrationTests.InProcess; @@ -205,5 +206,39 @@ public void Test() await TestServices.Editor.GoToDefinitionAsync(HangMitigatingCancellationToken); Assert.Equal("AbstractEditorTest.cs [embedded] [Read Only]", await TestServices.Shell.GetActiveWindowCaptionAsync(HangMitigatingCancellationToken)); } + + [IdeTheory] + [InlineData("ValueTuple valueTuple1;")] + [InlineData("ValueTuple valueTuple2;")] + [InlineData("ValueTuple valueTuple3;")] + [InlineData("ValueTuple valueTuple4;")] + [InlineData("ValueTuple valueTuple5;")] + [InlineData("ValueTuple valueTuple6;")] + [InlineData("ValueTuple valueTuple7;")] + [InlineData("ValueTuple valueTuple8;")] + [WorkItem("https://github.com/dotnet/roslyn/issues/71680")] + public async Task TestGotoDefinitionWithValueTuple(string expression) + { + var globalOptions = await TestServices.Shell.GetComponentModelServiceAsync(HangMitigatingCancellationToken); + globalOptions.SetGlobalOption(BlockStructureOptionsStorage.CollapseSourceLinkEmbeddedDecompiledFilesWhenFirstOpened, language: LanguageName, false); + + await TestServices.SolutionExplorer.AddFileAsync(ProjectName, "C.cs", cancellationToken: HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.OpenFileAsync(ProjectName, "C.cs", HangMitigatingCancellationToken); + await TestServices.Editor.SetTextAsync( +@$"using System; + +class C +{{ + void M() + {{ + {expression} + }} +}}", HangMitigatingCancellationToken); + + await TestServices.Editor.PlaceCaretAsync("ValueTuple", charsOffset: -1, HangMitigatingCancellationToken); + + await TestServices.Editor.GoToDefinitionAsync(HangMitigatingCancellationToken); + Assert.Equal($"ValueTuple [{FeaturesResources.Decompiled}] [Read Only]", await TestServices.Shell.GetActiveWindowCaptionAsync(HangMitigatingCancellationToken)); + } } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToGlobalImportsTests.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToGlobalImportsTests.cs index b4c7517eb1c5f..48b84a570c454 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToGlobalImportsTests.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpGoToGlobalImportsTests.cs @@ -21,7 +21,7 @@ public CSharpGoToGlobalImportsTests() : base(solutionName: nameof(CSharpGoToGlob { } - [IdeFact] + [IdeFact(Skip = "https://github.com/dotnet/roslyn/issues/72018")] public async Task TestGlobalImports() { // Make sure no glyph is in the margin at first. @@ -29,13 +29,22 @@ public async Task TestGlobalImports() await TestServices.SolutionExplorer.OpenFileAsync( ProjectName, "Class1.cs", HangMitigatingCancellationToken); - await TestServices.InheritanceMargin.EnableOptionsAndEnsureGlyphsAppearAsync(LanguageName, 1, HangMitigatingCancellationToken); + await TestServices.InheritanceMargin.EnableOptionsAsync(LanguageName, HangMitigatingCancellationToken); + await TestServices.InheritanceMargin.SetTextAndEnsureGlyphsAppearAsync(""" + namespace N + { + class C + { + } + } + """, 1, HangMitigatingCancellationToken); await TestServices.InheritanceMargin.ClickTheGlyphOnLine(1, HangMitigatingCancellationToken); // Move focus to menu item 'System' await TestServices.Input.SendWithoutActivateAsync(VirtualKeyCode.TAB, HangMitigatingCancellationToken); // Navigate to 'System' await TestServices.Input.SendWithoutActivateAsync(VirtualKeyCode.RETURN, HangMitigatingCancellationToken); + await TestServices.Workspace.WaitForAllAsyncOperationsAsync([FeatureAttribute.Workspace], HangMitigatingCancellationToken); await TestServices.Workspace.WaitForAllAsyncOperationsAsync([FeatureAttribute.InheritanceMargin], HangMitigatingCancellationToken); await TestServices.EditorVerifier.TextContainsAsync(@"global using global::System;$$", assertCaretPosition: true); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpSendToInteractive.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpSendToInteractive.cs index cbf2d4a3823b6..edb910f68fc75 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpSendToInteractive.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpSendToInteractive.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.IntegrationTest.Utilities; +using Microsoft.VisualStudio.LanguageServices.CSharp.Interactive; using Roslyn.VisualStudio.IntegrationTests; using Roslyn.VisualStudio.NewIntegrationTests.InProcess; using WindowsInput.Native; @@ -225,7 +226,7 @@ public async Task ResetInteractiveFromProjectAndVerify() await TestServices.SolutionExplorer.AddMetadataReferenceAsync(assembly, project, HangMitigatingCancellationToken); await TestServices.SolutionExplorer.SelectItemAsync(ProjectName, HangMitigatingCancellationToken); - await TestServices.Shell.ExecuteCommandAsync(WellKnownCommands.ProjectandSolutionContextMenus.Project.ResetCSharpInteractiveFromProject, HangMitigatingCancellationToken); + await TestServices.Shell.ExecuteCommandAsync(HangMitigatingCancellationToken); // Waiting for a long operation: build + reset from project await TestServices.InteractiveWindow.WaitForReplOutputAsync("using TestProj;", HangMitigatingCancellationToken); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ITextViewWindowVerifierInProcessExtensions.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ITextViewWindowVerifierInProcessExtensions.cs index ae3cf8d269d24..b15e527ba6344 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ITextViewWindowVerifierInProcessExtensions.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ITextViewWindowVerifierInProcessExtensions.cs @@ -109,12 +109,11 @@ public static async Task CodeActionAsync( { // wait for action to complete await textViewWindowVerifier.TestServices.Workspace.WaitForAllAsyncOperationsAsync( - new[] - { + [ FeatureAttribute.Workspace, FeatureAttribute.LightBulb, FeatureAttribute.Rename, - }, + ], cancellationToken); if (codeActionLogger.Messages.Any()) @@ -147,7 +146,7 @@ public static async Task CodeActionsNotShowingAsync(this ITextViewWindowVerifier public static async Task CurrentTokenTypeAsync(this ITextViewWindowVerifierInProcess textViewWindowVerifier, string tokenType, CancellationToken cancellationToken) { await textViewWindowVerifier.TestServices.Workspace.WaitForAllAsyncOperationsAsync( - new[] { FeatureAttribute.SolutionCrawlerLegacy, FeatureAttribute.DiagnosticService, FeatureAttribute.Classification }, + [FeatureAttribute.SolutionCrawlerLegacy, FeatureAttribute.DiagnosticService, FeatureAttribute.Classification], cancellationToken); var actualTokenTypes = await textViewWindowVerifier.TestServices.Editor.GetCurrentClassificationsAsync(cancellationToken); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowInProcess.cs index b2b548278efbc..bf450cd2d9fb9 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowInProcess.cs @@ -177,7 +177,7 @@ public async Task ShowWindowAsync(bool waitForPrompt, CancellationToken cancella { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); - await TestServices.Shell.ExecuteCommandAsync("View.C#Interactive", cancellationToken); + await TestServices.Shell.ExecuteCommandAsync(cancellationToken); if (waitForPrompt) { diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowVerifierInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowVerifierInProcess.cs index 58db7ca6376fc..5b0c4cd7f53db 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowVerifierInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/InteractiveWindowVerifierInProcess.cs @@ -13,7 +13,7 @@ namespace Roslyn.VisualStudio.NewIntegrationTests.InProcess [TestService] internal partial class InteractiveWindowVerifierInProcess : ITextViewWindowVerifierInProcess { - private static readonly char[] s_lineSeparators = { '\r', '\n' }; + private static readonly char[] s_lineSeparators = ['\r', '\n']; TestServices ITextViewWindowVerifierInProcess.TestServices => TestServices; diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ShellInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ShellInProcess.cs index 8d93f96eea9d0..8a857a34ac714 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ShellInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/ShellInProcess.cs @@ -12,6 +12,7 @@ using System.Windows.Controls; using System.Windows.Input; using Microsoft.CodeAnalysis.UnitTests; +using Microsoft.Internal.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; @@ -87,6 +88,30 @@ internal async Task IsActiveTabProvisionalAsync(CancellationToken cancella return (bool)isProvisionalObject; } + public Task ExecuteCommandAsync(CancellationToken cancellationToken) where TCommand : Commands.Command + => ExecuteRemotableCommandAsync(typeof(TCommand).FullName, cancellationToken); + + private async Task ExecuteRemotableCommandAsync(string commandName, CancellationToken cancellationToken) + { + await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + + var commandService = await GetRequiredGlobalServiceAsync(cancellationToken); + + ErrorHandler.ThrowOnFailure(commandService.GetControlDataSourceAsync( + (uint)__VSCOMMANDTYPES.cCommandTypeButton, + commandName, + timeout: 0, + out var dataSourceTask)); + + Assumes.NotNull(dataSourceTask); + if (dataSourceTask.GetResult() is not IVsUIDataSource commandSource) + { + throw new InvalidOperationException($"Error resolving command '{commandName}'."); + } + + ErrorHandler.ThrowOnFailure(commandSource.Invoke("Execute", pvaIn: null, out _)); + } + public async Task GetActiveDocumentFileNameAsync(CancellationToken cancellationToken) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); @@ -133,9 +158,9 @@ public async Task IsCommandAvailableAsync(Guid commandGuid, uint commandId var dispatcher = await TestServices.Shell.GetRequiredGlobalServiceAsync(cancellationToken); OLECMD[] commands = - { + [ new OLECMD { cmdID = commandId }, - }; + ]; var status = dispatcher.QueryStatus(commandGuid, (uint)commands.Length, commands, pCmdText: IntPtr.Zero); ErrorHandler.ThrowOnFailure(status); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs index 3fa909bf53c9d..6603f2fa0f213 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs @@ -192,14 +192,14 @@ private async Task CreateSolutionAsync(string solutionPath, string solutionName, ErrorHandler.ThrowOnFailure(solution.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0)); } - public async Task GetAssemblyReferencesAsync(string projectName, CancellationToken cancellationToken) + public async Task> GetAssemblyReferencesAsync(string projectName, CancellationToken cancellationToken) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var project = await GetProjectAsync(projectName, cancellationToken); var references = ((VSProject)project.Object).References.Cast() .Where(x => x.SourceProject == null) - .Select(x => x.Name + "," + x.Version + "," + x.PublicKeyToken).ToArray(); + .Select(x => (x.Name, x.Version, x.PublicKeyToken)).ToImmutableArray(); return references; } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerVerifierInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerVerifierInProcess.cs index 2a423b4fd4d99..59463a05a87c9 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerVerifierInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerVerifierInProcess.cs @@ -12,7 +12,6 @@ using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.TextManager.Interop; using Roslyn.Test.Utilities; -using Xunit; namespace Roslyn.VisualStudio.IntegrationTests.InProcess { @@ -68,18 +67,5 @@ public async Task AllDocumentsAreSavedAsync(CancellationToken cancellationToken) AssertEx.EqualOrDiff("", string.Join(Environment.NewLine, unsavedFiles), "Unexpected dirty documents after failed Save All"); } - - public async Task AssemblyReferencePresentAsync(string projectName, string assemblyName, string assemblyVersion, string assemblyPublicKeyToken, CancellationToken cancellationToken) - { - var assemblyReferences = await TestServices.SolutionExplorer.GetAssemblyReferencesAsync(projectName, cancellationToken); - var expectedAssemblyReference = assemblyName + "," + assemblyVersion + "," + assemblyPublicKeyToken.ToUpper(); - Assert.Contains(expectedAssemblyReference, assemblyReferences); - } - - public async Task ProjectReferencePresentAsync(string projectName, string referencedProjectName, CancellationToken cancellationToken) - { - var projectReferences = await TestServices.SolutionExplorer.GetProjectReferencesAsync(projectName, cancellationToken); - Assert.Contains(referencedProjectName, projectReferences); - } } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionVerifierInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionVerifierInProcess.cs index 4c1d56bcaaa62..a5e43a2381cba 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionVerifierInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionVerifierInProcess.cs @@ -2,8 +2,10 @@ // 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.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.Extensibility.Testing; using Xunit; @@ -15,11 +17,36 @@ internal partial class SolutionVerifierInProcess public async Task AssemblyReferencePresentAsync(string projectName, string assemblyName, string assemblyVersion, string assemblyPublicKeyToken, CancellationToken cancellationToken) { var assemblyReferences = await TestServices.SolutionExplorer.GetAssemblyReferencesAsync(projectName, cancellationToken); - var expectedAssemblyReference = assemblyName + "," + assemblyVersion + "," + assemblyPublicKeyToken.ToUpper(); + var expectedAssemblyReference = (assemblyName, assemblyVersion, assemblyPublicKeyToken: assemblyPublicKeyToken.ToUpper()); + if (assemblyReferences.Contains(expectedAssemblyReference)) + return; + + var assemblyReferencesMatchingName = assemblyReferences.WhereAsArray(reference => string.Equals(reference.name, expectedAssemblyReference.assemblyName, StringComparison.OrdinalIgnoreCase)); + if (!assemblyReferencesMatchingName.IsEmpty) + assemblyReferences = assemblyReferencesMatchingName; + + // 17.9.0 Preview 2.0 through 17.9.0 Preview 2.1 + if (await TestServices.Shell.GetVersionAsync(cancellationToken) >= Version.Parse("17.9.34407.89") + && await TestServices.Shell.GetVersionAsync(cancellationToken) <= Version.Parse("17.9.34414.90") + && !assemblyReferencesMatchingName.IsEmpty) + { + // The actual assembly version has a number like: + // 0.0.527041792.678 + // 0.0.528033936.678 + // 0.0.292991664.480 + // 0.0.205444464.480 + // + // The actual public key token is empty in these test cases. + // + // Since we can't predict the exact outcome, only validate the assembly name (indirectly by knowing + // assemblyReferencesMatchingName is not empty). + return; + } + Assert.Contains(expectedAssemblyReference, assemblyReferences); } - public async Task ProjectReferencePresent(string projectName, string referencedProjectName, CancellationToken cancellationToken) + public async Task ProjectReferencePresentAsync(string projectName, string referencedProjectName, CancellationToken cancellationToken) { var projectReferences = await TestServices.SolutionExplorer.GetProjectReferencesAsync(projectName, cancellationToken); Assert.Contains(referencedProjectName, projectReferences); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/WorkaroundsInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/WorkaroundsInProcess.cs index bc11dd8cfff55..17f4ef568cf02 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/WorkaroundsInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/WorkaroundsInProcess.cs @@ -116,6 +116,17 @@ public async Task DisableAutoSurroundAsync(CancellationToken cancellationToken) var result = writer.RequestCommit("Integration test workaround"); Assert.True(result.Outcome is SettingCommitOutcome.Success or SettingCommitOutcome.NoChangesQueued); } + + // 17.9 P2 used a different name for the same setting + settingName = "textEditor.general.autoBraceSurround"; + settingRetrieval = reader.GetValue(settingName); + if (settingRetrieval.Value) + { + var writer = settingManager.GetWriter("Roslyn Integration test"); + writer.EnqueueChange(settingName, false); + var result = writer.RequestCommit("Integration test workaround"); + Assert.True(result.Outcome is SettingCommitOutcome.Success or SettingCommitOutcome.NoChangesQueued); + } } } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/VisualBasic/BasicAddMissingReference.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/VisualBasic/BasicAddMissingReference.cs index 57a32be2318b2..27a55a720cce3 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/VisualBasic/BasicAddMissingReference.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/VisualBasic/BasicAddMissingReference.cs @@ -180,7 +180,7 @@ await TestServices.SolutionVerifier.AssemblyReferencePresentAsync( await TestServices.Editor.PlaceCaretAsync("a.bar", charsOffset: 1, HangMitigatingCancellationToken); await TestServices.Editor.InvokeCodeActionListAsync(HangMitigatingCancellationToken); await TestServices.EditorVerifier.CodeActionAsync("Add project reference to 'ClassLibrary3'.", applyFix: true, cancellationToken: HangMitigatingCancellationToken); - await TestServices.SolutionVerifier.ProjectReferencePresent( + await TestServices.SolutionVerifier.ProjectReferencePresentAsync( projectName: ConsoleProjectName, referencedProjectName: ClassLibrary3Name, HangMitigatingCancellationToken); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/WellKnownCommands.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/WellKnownCommands.cs index 0f922105cea16..9e8943fea642f 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/WellKnownCommands.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/WellKnownCommands.cs @@ -54,14 +54,6 @@ public static class InteractiveConsole public static readonly CommandID ExecuteInInteractive = new(InteractiveShell::Guids.InteractiveCommandSetId, 268); } - public static class ProjectandSolutionContextMenus - { - public static class Project - { - public static readonly CommandID ResetCSharpInteractiveFromProject = new(ID.InteractiveCommands.CSharpInteractiveCommandSetId, ID.InteractiveCommands.ResetInteractiveFromProject); - } - } - public static class Refactor { public const VSConstants.VSStd2KCmdID EncapsulateField = VSConstants.VSStd2KCmdID.ENCAPSULATEFIELD; diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspaceBase.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspaceBase.cs index c006930c72b96..b548c5dc6fc04 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspaceBase.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspaceBase.cs @@ -66,7 +66,8 @@ Private e As Exception public virtual async Task MetadataReference() { - await TestServices.SolutionExplorer.AddDllReferenceAsync("TestProj", typeof(System.Windows.Point).Assembly.Location, HangMitigatingCancellationToken); + var reference = "WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; + await TestServices.SolutionExplorer.AddMetadataReferenceAsync(reference, "TestProj", HangMitigatingCancellationToken); await TestServices.Workspace.WaitForAllAsyncOperationsAsync([FeatureAttribute.Workspace], HangMitigatingCancellationToken); await TestServices.Editor.SetTextAsync("class C { System.Windows.Point p; }", HangMitigatingCancellationToken); @@ -79,7 +80,7 @@ public virtual async Task MetadataReference() await TestServices.EditorVerifier.CurrentTokenTypeAsync("identifier", HangMitigatingCancellationToken); } - [IdeFact] + [IdeFact(Skip = "https://github.com/dotnet/roslyn/issues/72018")] public async Task ProjectReference() { await InitializeWithDefaultSolution(); diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesDesktop.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesDesktop.cs index c0558fe3727ed..2a0f488b08c11 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesDesktop.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesDesktop.cs @@ -3,30 +3,25 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; -using Roslyn.Test.Utilities; using Xunit; -using Xunit.Abstractions; -namespace Roslyn.VisualStudio.NewIntegrationTests.Workspaces +namespace Roslyn.VisualStudio.NewIntegrationTests.Workspaces; + +[Trait(Traits.Feature, Traits.Features.Workspace)] +public class WorkspacesDesktop : WorkspaceBase { - [Trait(Traits.Feature, Traits.Features.Workspace)] - public class WorkspacesDesktop : WorkspaceBase + public WorkspacesDesktop() + : base(WellKnownProjectTemplates.ClassLibrary) { - public WorkspacesDesktop() - : base(WellKnownProjectTemplates.ClassLibrary) - { - } + } - [IdeFact] - public override async Task MetadataReference() - { - await InitializeWithDefaultSolution(); - await base.MetadataReference(); - } + [IdeFact] + public override async Task MetadataReference() + { + await InitializeWithDefaultSolution(); + await base.MetadataReference(); } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesNetCore.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesNetCore.cs index 774add47a5d97..a5ed33d83d2e0 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesNetCore.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/Workspace/WorkspacesNetCore.cs @@ -3,52 +3,50 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.IntegrationTest.Utilities; using Roslyn.Test.Utilities; using Xunit; -using Xunit.Abstractions; -namespace Roslyn.VisualStudio.NewIntegrationTests.Workspaces +namespace Roslyn.VisualStudio.NewIntegrationTests.Workspaces; + +[Trait(Traits.Feature, Traits.Features.NetCore)] +[Trait(Traits.Feature, Traits.Features.Workspace)] +public class WorkspacesNetCore : WorkspaceBase { - [Trait(Traits.Feature, Traits.Features.NetCore)] - [Trait(Traits.Feature, Traits.Features.Workspace)] - public class WorkspacesNetCore : WorkspaceBase + public WorkspacesNetCore() + : base(WellKnownProjectTemplates.CSharpNetCoreClassLibrary) { - public WorkspacesNetCore() - : base(WellKnownProjectTemplates.CSharpNetCoreClassLibrary) - { - } + } - [IdeFact, Trait(Traits.Feature, Traits.Features.Workspace)] - [Trait(Traits.Feature, Traits.Features.NetCore)] - [WorkItem("https://github.com/dotnet/roslyn/issues/34264")] - public override async Task MetadataReference() - { - await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(WorkspacesNetCore), HangMitigatingCancellationToken); - await TestServices.SolutionExplorer.AddCustomProjectAsync(ProjectName, ".csproj", @" + [IdeFact(Skip = "https://github.com/dotnet/roslyn/issues/72018")] + [Trait(Traits.Feature, Traits.Features.Workspace)] + [Trait(Traits.Feature, Traits.Features.NetCore)] + [WorkItem("https://github.com/dotnet/roslyn/issues/34264")] + public override async Task MetadataReference() + { + await TestServices.SolutionExplorer.CreateSolutionAsync(nameof(WorkspacesNetCore), HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.AddCustomProjectAsync(ProjectName, ".csproj", @" - net46 + net472 ", HangMitigatingCancellationToken); - await TestServices.SolutionExplorer.AddFileAsync(ProjectName, "Class1.cs", contents: string.Empty, open: true, cancellationToken: HangMitigatingCancellationToken); - await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken); - await TestServices.Workspace.WaitForAllAsyncOperationsAsync([FeatureAttribute.Workspace], HangMitigatingCancellationToken); - await TestServices.Workspace.SetFullSolutionAnalysisAsync(true, HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.AddFileAsync(ProjectName, "Class1.cs", contents: string.Empty, open: true, cancellationToken: HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.RestoreNuGetPackagesAsync(HangMitigatingCancellationToken); + await TestServices.Workspace.WaitForAllAsyncOperationsAsync([FeatureAttribute.Workspace], HangMitigatingCancellationToken); + await TestServices.Workspace.SetFullSolutionAnalysisAsync(true, HangMitigatingCancellationToken); - await base.MetadataReference(); - } + await base.MetadataReference(); + } - [IdeFact(Skip = "https://github.com/dotnet/roslyn/issues/30599")] - [Trait(Traits.Feature, Traits.Features.Workspace)] - [Trait(Traits.Feature, Traits.Features.NetCore)] - public override async Task RenamingOpenFiles() - { - await InitializeWithDefaultSolution(); - await base.RenamingOpenFiles(); - } + [IdeFact(Skip = "https://github.com/dotnet/roslyn/issues/30599")] + [Trait(Traits.Feature, Traits.Features.Workspace)] + [Trait(Traits.Feature, Traits.Features.NetCore)] + public override async Task RenamingOpenFiles() + { + await InitializeWithDefaultSolution(); + await base.RenamingOpenFiles(); } } diff --git a/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj b/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj index 7506d1eb6d03f..ee3c8f5f5dc30 100644 --- a/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj +++ b/src/VisualStudio/Setup/Roslyn.VisualStudio.Setup.csproj @@ -1,4 +1,4 @@ - + @@ -15,6 +15,7 @@ false $(CommonExtensionInstallationRoot) $(LanguageServicesExtensionInstallationFolder) + true Microsoft.CodeAnalysis.LanguageServices @@ -222,7 +223,7 @@ CSharpVisualStudio - BuiltProjectOutputGroup;PkgDefProjectOutputGroup;ContentFilesProjectOutputGroup;SatelliteDllsProjectOutputGroup + BuiltProjectOutputGroup;PkgDefProjectOutputGroup;ContentFilesProjectOutputGroup;SatelliteDllsProjectOutputGroup;ExtensionJsonOutputGroup true BindingRedirect diff --git a/src/VisualStudio/Setup/source.extension.vsixmanifest b/src/VisualStudio/Setup/source.extension.vsixmanifest index 1a7988a16eda8..5153d20eea9b9 100644 --- a/src/VisualStudio/Setup/source.extension.vsixmanifest +++ b/src/VisualStudio/Setup/source.extension.vsixmanifest @@ -8,7 +8,7 @@ EULA.rtf true - + amd64 diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf index 136b4dcb8a28c..6754b224ea9b5 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + Odebrat nepotřebné importy {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf index b8229bab0fb78..5f44e86f2b776 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + Supprimer les importations inutiles {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf index 1dfc5909d8754..282b439aaa355 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + 不要なインポートの削除 {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf index 6f197108c1346..220adee27b170 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + Usuń niepotrzebne importy {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf index c67ee1bfcc09e..801d59f2a2d99 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + Remover as Importações desnecessárias {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf index f5b5db12203ff..20749fed8fe6b 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + Gereksiz içeri aktarmaları kaldır {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf index 80c45baed634b..5c73f3da6c0ff 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf @@ -64,7 +64,7 @@ Remove unnecessary imports - Remove unnecessary imports + 移除不必要的 Import {Locked="Import"} 'import' is a Visual Basic keyword and should not be localized diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index 1ffd0a1a76542..1e6fe18897c17 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -2747,7 +2747,7 @@ public override SyntaxNode ReplaceNode(SyntaxNode root, SyntaxNode declaration, var index = IndexOf(GetSubDeclarations(fullDecl), declaration); // replace declaration with multiple declarations - return ReplaceRange(root, fullDecl, SplitAndReplace(fullDecl, index, new[] { newDeclaration })); + return ReplaceRange(root, fullDecl, SplitAndReplace(fullDecl, index, [newDeclaration])); } // attempt normal replace @@ -3055,8 +3055,8 @@ private static SyntaxNode ShiftTrivia(SyntaxNode root, SyntaxNode node) var newNode = node.WithTrailingTrivia(node.GetTrailingTrivia().AddRange(previousToken.TrailingTrivia)); var newPreviousToken = previousToken.WithTrailingTrivia(default(SyntaxTriviaList)); return root.ReplaceSyntax( - nodes: new[] { node }, computeReplacementNode: (o, r) => newNode, - tokens: new[] { previousToken }, computeReplacementToken: (o, r) => newPreviousToken, + nodes: [node], computeReplacementNode: (o, r) => newNode, + tokens: [previousToken], computeReplacementToken: (o, r) => newPreviousToken, trivia: null, computeReplacementTrivia: null); } diff --git a/src/Workspaces/CSharp/Portable/Serialization/CSharpOptionsSerializationService.cs b/src/Workspaces/CSharp/Portable/Serialization/CSharpOptionsSerializationService.cs index ec95689140f2a..6682c746c58a2 100644 --- a/src/Workspaces/CSharp/Portable/Serialization/CSharpOptionsSerializationService.cs +++ b/src/Workspaces/CSharp/Portable/Serialization/CSharpOptionsSerializationService.cs @@ -10,6 +10,7 @@ using System.Threading; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Serialization; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Serialization @@ -28,7 +29,7 @@ public override void WriteTo(CompilationOptions options, ObjectWriter writer, Ca WriteCompilationOptionsTo(options, writer, cancellationToken); var csharpOptions = (CSharpCompilationOptions)options; - writer.WriteValue(csharpOptions.Usings.ToArray()); + writer.WriteArray(csharpOptions.Usings, static (w, u) => w.WriteString(u)); writer.WriteBoolean(csharpOptions.AllowUnsafe); writer.WriteByte((byte)csharpOptions.NullableContextOptions); } @@ -39,21 +40,19 @@ public override void WriteTo(ParseOptions options, ObjectWriter writer) var csharpOptions = (CSharpParseOptions)options; writer.WriteInt32((int)csharpOptions.SpecifiedLanguageVersion); - writer.WriteValue(options.PreprocessorSymbolNames.ToArray()); + writer.WriteArray(options.PreprocessorSymbolNames.ToImmutableArrayOrEmpty(), static (w, p) => w.WriteString(p)); } public override CompilationOptions ReadCompilationOptionsFrom(ObjectReader reader, CancellationToken cancellationToken) { - ReadCompilationOptionsFrom( - reader, - out var outputKind, out var reportSuppressedDiagnostics, out var moduleName, out var mainTypeName, out var scriptClassName, - out var optimizationLevel, out var checkOverflow, out var cryptoKeyContainer, out var cryptoKeyFile, out var cryptoPublicKey, - out var delaySign, out var platform, out var generalDiagnosticOption, out var warningLevel, out var specificDiagnosticOptions, - out var concurrentBuild, out var deterministic, out var publicSign, out var metadataImportOptions, - out var xmlReferenceResolver, out var sourceReferenceResolver, out var metadataReferenceResolver, out var assemblyIdentityComparer, - out var strongNameProvider, cancellationToken); + var (outputKind, reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName, + optimizationLevel, checkOverflow, cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, + delaySign, platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions, + concurrentBuild, deterministic, publicSign, metadataImportOptions, + xmlReferenceResolver, sourceReferenceResolver, metadataReferenceResolver, assemblyIdentityComparer, + strongNameProvider) = ReadCompilationOptionsPieces(reader, cancellationToken); - var usings = reader.ReadArray(); + var usings = reader.ReadArray(static r => r.ReadString()); var allowUnsafe = reader.ReadBoolean(); var nullableContextOptions = (NullableContextOptions)reader.ReadByte(); @@ -66,10 +65,10 @@ public override CompilationOptions ReadCompilationOptionsFrom(ObjectReader reade public override ParseOptions ReadParseOptionsFrom(ObjectReader reader, CancellationToken cancellationToken) { - ReadParseOptionsFrom(reader, out var kind, out var documentationMode, out var features, cancellationToken); + var (kind, documentationMode, features) = ReadParseOptionsPieces(reader, cancellationToken); var languageVersion = (LanguageVersion)reader.ReadInt32(); - var preprocessorSymbolNames = reader.ReadArray(); + var preprocessorSymbolNames = reader.ReadArray(static r => r.ReadString()); var options = new CSharpParseOptions(languageVersion, documentationMode, kind, preprocessorSymbolNames); return options.WithFeatures(features); diff --git a/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs b/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs index 6decc155d0172..7024de4195a20 100644 --- a/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs +++ b/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs @@ -784,7 +784,7 @@ public void M2([A] String p2) { } metadataReferences: new[] { TestMetadata.Net451.mscorlib })); var project = emptyProject - .AddMetadataReferences(new[] { otherAssemblyReference }) + .AddMetadataReferences([otherAssemblyReference]) .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); project = project.AddDocument("duplicate.cs", externalCode).Project; @@ -833,7 +833,7 @@ private static MetadataReference GetInMemoryAssemblyReferenceForCode(string code var tree = CSharpSyntaxTree.ParseText(code); var compilation = CSharpCompilation - .Create("test.dll", new[] { tree }) + .Create("test.dll", [tree]) .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) .AddReferences(TestMetadata.Net451.mscorlib); diff --git a/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs b/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs index fc4441f7d62d8..31fb62892bac8 100644 --- a/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs +++ b/src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs @@ -225,7 +225,7 @@ public class MyAttribute : Attribute { public int Value {get; set;} }", var attributes = Generator.GetAttributes(Generator.AddAttributes( Generator.NamespaceDeclaration("n"), Generator.Attribute("Attr"))); - Assert.True(attributes.Count == 1); + Assert.Single(attributes); } private static AttributeData GetAttributeData(string decl, string use) @@ -282,7 +282,7 @@ public void TestTypeExpressions() VerifySyntax(Generator.TupleElementExpression(intType, "y"), "global::System.Int32 y"); VerifySyntax(Generator.TupleTypeExpression(Generator.TupleElementExpression(Generator.IdentifierName("x")), Generator.TupleElementExpression(Generator.IdentifierName("y"))), "(x, y)"); VerifySyntax(Generator.TupleTypeExpression(new[] { intType, intType }), "(global::System.Int32, global::System.Int32)"); - VerifySyntax(Generator.TupleTypeExpression(new[] { intType, intType }, new[] { "x", "y" }), "(global::System.Int32 x, global::System.Int32 y)"); + VerifySyntax(Generator.TupleTypeExpression(new[] { intType, intType }, ["x", "y"]), "(global::System.Int32 x, global::System.Int32 y)"); } [Fact] @@ -526,11 +526,11 @@ public void TestNameOfExpressions() public void TestTupleExpression() { VerifySyntax(Generator.TupleExpression( - new[] { Generator.IdentifierName("x"), Generator.IdentifierName("y") }), "(x, y)"); + [Generator.IdentifierName("x"), Generator.IdentifierName("y")]), "(x, y)"); - VerifySyntax(Generator.TupleExpression( - new[] { Generator.Argument("goo", RefKind.None, Generator.IdentifierName("x")), - Generator.Argument("bar", RefKind.None, Generator.IdentifierName("y")) }), "(goo: x, bar: y)"); + VerifySyntax(Generator.TupleExpression([ + Generator.Argument("goo", RefKind.None, Generator.IdentifierName("x")), + Generator.Argument("bar", RefKind.None, Generator.IdentifierName("y"))]), "(goo: x, bar: y)"); } [Fact] @@ -595,42 +595,42 @@ public void TestSwitchStatements() VerifySyntax( Generator.SwitchStatement(Generator.IdentifierName("x"), Generator.SwitchSection(Generator.IdentifierName("y"), - new[] { Generator.IdentifierName("z") })), + [Generator.IdentifierName("z")])), "switch (x)\r\n{\r\n case y:\r\n z;\r\n}"); VerifySyntax( Generator.SwitchStatement(Generator.IdentifierName("x"), Generator.SwitchSection( - new[] { Generator.IdentifierName("y"), Generator.IdentifierName("p"), Generator.IdentifierName("q") }, - new[] { Generator.IdentifierName("z") })), + [Generator.IdentifierName("y"), Generator.IdentifierName("p"), Generator.IdentifierName("q")], + [Generator.IdentifierName("z")])), "switch (x)\r\n{\r\n case y:\r\n case p:\r\n case q:\r\n z;\r\n}"); VerifySyntax( Generator.SwitchStatement(Generator.IdentifierName("x"), Generator.SwitchSection(Generator.IdentifierName("y"), - new[] { Generator.IdentifierName("z") }), + [Generator.IdentifierName("z")]), Generator.SwitchSection(Generator.IdentifierName("a"), - new[] { Generator.IdentifierName("b") })), + [Generator.IdentifierName("b")])), "switch (x)\r\n{\r\n case y:\r\n z;\r\n case a:\r\n b;\r\n}"); VerifySyntax( Generator.SwitchStatement(Generator.IdentifierName("x"), Generator.SwitchSection(Generator.IdentifierName("y"), - new[] { Generator.IdentifierName("z") }), + [Generator.IdentifierName("z")]), Generator.DefaultSwitchSection( - new[] { Generator.IdentifierName("b") })), + [Generator.IdentifierName("b")])), "switch (x)\r\n{\r\n case y:\r\n z;\r\n default:\r\n b;\r\n}"); VerifySyntax( Generator.SwitchStatement(Generator.IdentifierName("x"), Generator.SwitchSection(Generator.IdentifierName("y"), - new[] { Generator.ExitSwitchStatement() })), + [Generator.ExitSwitchStatement()])), "switch (x)\r\n{\r\n case y:\r\n break;\r\n}"); VerifySyntax( - Generator.SwitchStatement(Generator.TupleExpression(new[] { Generator.IdentifierName("x1"), Generator.IdentifierName("x2") }), + Generator.SwitchStatement(Generator.TupleExpression([Generator.IdentifierName("x1"), Generator.IdentifierName("x2")]), Generator.SwitchSection(Generator.IdentifierName("y"), - new[] { Generator.IdentifierName("z") })), + [Generator.IdentifierName("z")])), "switch (x1, x2)\r\n{\r\n case y:\r\n z;\r\n}"); } @@ -639,15 +639,15 @@ public void TestSwitchStatements() public void TestUsingStatements() { VerifySyntax( - Generator.UsingStatement(Generator.IdentifierName("x"), new[] { Generator.IdentifierName("y") }), + Generator.UsingStatement(Generator.IdentifierName("x"), [Generator.IdentifierName("y")]), "using (x)\r\n{\r\n y;\r\n}"); VerifySyntax( - Generator.UsingStatement("x", Generator.IdentifierName("y"), new[] { Generator.IdentifierName("z") }), + Generator.UsingStatement("x", Generator.IdentifierName("y"), [Generator.IdentifierName("z")]), "using (var x = y)\r\n{\r\n z;\r\n}"); VerifySyntax( - Generator.UsingStatement(Generator.IdentifierName("x"), "y", Generator.IdentifierName("z"), new[] { Generator.IdentifierName("q") }), + Generator.UsingStatement(Generator.IdentifierName("x"), "y", Generator.IdentifierName("z"), [Generator.IdentifierName("q")]), "using (x y = z)\r\n{\r\n q;\r\n}"); } @@ -655,7 +655,7 @@ public void TestUsingStatements() public void TestLockStatements() { VerifySyntax( - Generator.LockStatement(Generator.IdentifierName("x"), new[] { Generator.IdentifierName("y") }), + Generator.LockStatement(Generator.IdentifierName("x"), [Generator.IdentifierName("y")]), "lock (x)\r\n{\r\n y;\r\n}"); } @@ -664,31 +664,31 @@ public void TestTryCatchStatements() { VerifySyntax( Generator.TryCatchStatement( - new[] { Generator.IdentifierName("x") }, + [Generator.IdentifierName("x")], Generator.CatchClause(Generator.IdentifierName("y"), "z", - new[] { Generator.IdentifierName("a") })), + [Generator.IdentifierName("a")])), "try\r\n{\r\n x;\r\n}\r\ncatch (y z)\r\n{\r\n a;\r\n}"); VerifySyntax( Generator.TryCatchStatement( - new[] { Generator.IdentifierName("s") }, + [Generator.IdentifierName("s")], Generator.CatchClause(Generator.IdentifierName("x"), "y", - new[] { Generator.IdentifierName("z") }), + [Generator.IdentifierName("z")]), Generator.CatchClause(Generator.IdentifierName("a"), "b", - new[] { Generator.IdentifierName("c") })), + [Generator.IdentifierName("c")])), "try\r\n{\r\n s;\r\n}\r\ncatch (x y)\r\n{\r\n z;\r\n}\r\ncatch (a b)\r\n{\r\n c;\r\n}"); VerifySyntax( Generator.TryCatchStatement( - new[] { Generator.IdentifierName("s") }, - new[] { Generator.CatchClause(Generator.IdentifierName("x"), "y", new[] { Generator.IdentifierName("z") }) }, - new[] { Generator.IdentifierName("a") }), + [Generator.IdentifierName("s")], + [Generator.CatchClause(Generator.IdentifierName("x"), "y", [Generator.IdentifierName("z")])], + [Generator.IdentifierName("a")]), "try\r\n{\r\n s;\r\n}\r\ncatch (x y)\r\n{\r\n z;\r\n}\r\nfinally\r\n{\r\n a;\r\n}"); VerifySyntax( Generator.TryFinallyStatement( - new[] { Generator.IdentifierName("x") }, - new[] { Generator.IdentifierName("a") }), + [Generator.IdentifierName("x")], + [Generator.IdentifierName("a")]), "try\r\n{\r\n x;\r\n}\r\nfinally\r\n{\r\n a;\r\n}"); } @@ -697,7 +697,7 @@ public void TestWhileStatements() { VerifySyntax( Generator.WhileStatement(Generator.IdentifierName("x"), - new[] { Generator.IdentifierName("y") }), + [Generator.IdentifierName("y")]), "while (x)\r\n{\r\n y;\r\n}"); VerifySyntax( @@ -733,27 +733,27 @@ public void TestLambdaExpressions() "() => y"); VerifySyntax( - Generator.ValueReturningLambdaExpression("x", new[] { Generator.ReturnStatement(Generator.IdentifierName("y")) }), + Generator.ValueReturningLambdaExpression("x", [Generator.ReturnStatement(Generator.IdentifierName("y"))]), "x =>\r\n{\r\n return y;\r\n}"); VerifySyntax( - Generator.ValueReturningLambdaExpression(new[] { Generator.LambdaParameter("x"), Generator.LambdaParameter("y") }, new[] { Generator.ReturnStatement(Generator.IdentifierName("z")) }), + Generator.ValueReturningLambdaExpression(new[] { Generator.LambdaParameter("x"), Generator.LambdaParameter("y") }, [Generator.ReturnStatement(Generator.IdentifierName("z"))]), "(x, y) =>\r\n{\r\n return z;\r\n}"); VerifySyntax( - Generator.ValueReturningLambdaExpression(new SyntaxNode[] { }, new[] { Generator.ReturnStatement(Generator.IdentifierName("y")) }), + Generator.ValueReturningLambdaExpression(new SyntaxNode[] { }, [Generator.ReturnStatement(Generator.IdentifierName("y"))]), "() =>\r\n{\r\n return y;\r\n}"); VerifySyntax( - Generator.VoidReturningLambdaExpression("x", new[] { Generator.IdentifierName("y") }), + Generator.VoidReturningLambdaExpression("x", [Generator.IdentifierName("y")]), "x =>\r\n{\r\n y;\r\n}"); VerifySyntax( - Generator.VoidReturningLambdaExpression(new[] { Generator.LambdaParameter("x"), Generator.LambdaParameter("y") }, new[] { Generator.IdentifierName("z") }), + Generator.VoidReturningLambdaExpression(new[] { Generator.LambdaParameter("x"), Generator.LambdaParameter("y") }, [Generator.IdentifierName("z")]), "(x, y) =>\r\n{\r\n z;\r\n}"); VerifySyntax( - Generator.VoidReturningLambdaExpression(new SyntaxNode[] { }, new[] { Generator.IdentifierName("y") }), + Generator.VoidReturningLambdaExpression(new SyntaxNode[] { }, [Generator.IdentifierName("y")]), "() =>\r\n{\r\n y;\r\n}"); VerifySyntax( @@ -807,7 +807,7 @@ public void TestMethodDeclarations() "void m()\r\n{\r\n}"); VerifySyntax( - Generator.MethodDeclaration("m", typeParameters: new[] { "x", "y" }), + Generator.MethodDeclaration("m", typeParameters: ["x", "y"]), "void m()\r\n{\r\n}"); VerifySyntax( @@ -815,15 +815,15 @@ public void TestMethodDeclarations() "x m()\r\n{\r\n}"); VerifySyntax( - Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("x"), statements: new[] { Generator.IdentifierName("y") }), + Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("x"), statements: [Generator.IdentifierName("y")]), "x m()\r\n{\r\n y;\r\n}"); VerifySyntax( - Generator.MethodDeclaration("m", parameters: new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, returnType: Generator.IdentifierName("x")), + Generator.MethodDeclaration("m", parameters: [Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], returnType: Generator.IdentifierName("x")), "x m(y z)\r\n{\r\n}"); VerifySyntax( - Generator.MethodDeclaration("m", parameters: new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y"), Generator.IdentifierName("a")) }, returnType: Generator.IdentifierName("x")), + Generator.MethodDeclaration("m", parameters: [Generator.ParameterDeclaration("z", Generator.IdentifierName("y"), Generator.IdentifierName("a"))], returnType: Generator.IdentifierName("x")), "x m(y z = a)\r\n{\r\n}"); VerifySyntax( @@ -839,7 +839,7 @@ public void TestMethodDeclarations() "partial void m();"); VerifySyntax( - Generator.MethodDeclaration("m", modifiers: DeclarationModifiers.Partial, statements: new[] { Generator.IdentifierName("y") }), + Generator.MethodDeclaration("m", modifiers: DeclarationModifiers.Partial, statements: [Generator.IdentifierName("y")]), "partial void m()\r\n{\r\n y;\r\n}"); VerifySyntax( @@ -1004,13 +1004,13 @@ public void TestConstructorDeclaration() "public static c()\r\n{\r\n}"); VerifySyntax( - Generator.ConstructorDeclaration("c", new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }), + Generator.ConstructorDeclaration("c", [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))]), "c(t p)\r\n{\r\n}"); VerifySyntax( Generator.ConstructorDeclaration("c", - parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }, - baseConstructorArguments: new[] { Generator.IdentifierName("p") }), + parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))], + baseConstructorArguments: [Generator.IdentifierName("p")]), "c(t p) : base(p)\r\n{\r\n}"); } @@ -1050,19 +1050,19 @@ public void TestPropertyDeclarations() "required x p { get; set; }"); VerifySyntax( - Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), modifiers: DeclarationModifiers.ReadOnly, getAccessorStatements: new[] { Generator.IdentifierName("y") }), + Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), modifiers: DeclarationModifiers.ReadOnly, getAccessorStatements: [Generator.IdentifierName("y")]), "x p\r\n{\r\n get\r\n {\r\n y;\r\n }\r\n}"); VerifySyntax( - Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), modifiers: DeclarationModifiers.WriteOnly, setAccessorStatements: new[] { Generator.IdentifierName("y") }), + Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), modifiers: DeclarationModifiers.WriteOnly, setAccessorStatements: [Generator.IdentifierName("y")]), "x p\r\n{\r\n set\r\n {\r\n y;\r\n }\r\n}"); VerifySyntax( - Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), setAccessorStatements: new[] { Generator.IdentifierName("y") }), + Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), setAccessorStatements: [Generator.IdentifierName("y")]), "x p\r\n{\r\n get;\r\n set\r\n {\r\n y;\r\n }\r\n}"); VerifySyntax( - Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), getAccessorStatements: [], setAccessorStatements: new[] { Generator.IdentifierName("y") }), + Generator.PropertyDeclaration("p", Generator.IdentifierName("x"), getAccessorStatements: [], setAccessorStatements: [Generator.IdentifierName("y")]), "x p\r\n{\r\n get\r\n {\r\n }\r\n\r\n set\r\n {\r\n y;\r\n }\r\n}"); } @@ -1070,47 +1070,47 @@ public void TestPropertyDeclarations() public void TestIndexerDeclarations() { VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract | DeclarationModifiers.ReadOnly), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract | DeclarationModifiers.ReadOnly), "abstract x this[y z] { get; }"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract | DeclarationModifiers.WriteOnly), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract | DeclarationModifiers.WriteOnly), "abstract x this[y z] { set; }"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract), "abstract x this[y z] { get; set; }"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.ReadOnly), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.ReadOnly), "x this[y z]\r\n{\r\n get\r\n {\r\n }\r\n}"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.WriteOnly), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.WriteOnly), "x this[y z]\r\n{\r\n set\r\n {\r\n }\r\n}"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.ReadOnly, - getAccessorStatements: new[] { Generator.IdentifierName("a") }), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.ReadOnly, + getAccessorStatements: [Generator.IdentifierName("a")]), "x this[y z]\r\n{\r\n get\r\n {\r\n a;\r\n }\r\n}"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.WriteOnly, - setAccessorStatements: new[] { Generator.IdentifierName("a") }), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.WriteOnly, + setAccessorStatements: [Generator.IdentifierName("a")]), "x this[y z]\r\n{\r\n set\r\n {\r\n a;\r\n }\r\n}"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x")), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x")), "x this[y z]\r\n{\r\n get\r\n {\r\n }\r\n\r\n set\r\n {\r\n }\r\n}"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), - setAccessorStatements: new[] { Generator.IdentifierName("a") }), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), + setAccessorStatements: [Generator.IdentifierName("a")]), "x this[y z]\r\n{\r\n get\r\n {\r\n }\r\n\r\n set\r\n {\r\n a;\r\n }\r\n}"); VerifySyntax( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), - getAccessorStatements: new[] { Generator.IdentifierName("a") }, setAccessorStatements: new[] { Generator.IdentifierName("b") }), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), + getAccessorStatements: [Generator.IdentifierName("a")], setAccessorStatements: [Generator.IdentifierName("b")]), "x this[y z]\r\n{\r\n get\r\n {\r\n a;\r\n }\r\n\r\n set\r\n {\r\n b;\r\n }\r\n}"); } @@ -1146,7 +1146,7 @@ public void TestEventPropertyDeclarations() "event t ep\r\n{\r\n add\r\n {\r\n }\r\n\r\n remove\r\n {\r\n }\r\n}"); VerifySyntax( - Generator.CustomEventDeclaration("ep", Generator.IdentifierName("t"), addAccessorStatements: new[] { Generator.IdentifierName("s") }, removeAccessorStatements: new[] { Generator.IdentifierName("s2") }), + Generator.CustomEventDeclaration("ep", Generator.IdentifierName("t"), addAccessorStatements: [Generator.IdentifierName("s")], removeAccessorStatements: [Generator.IdentifierName("s2")]), "event t ep\r\n{\r\n add\r\n {\r\n s;\r\n }\r\n\r\n remove\r\n {\r\n s2;\r\n }\r\n}"); } @@ -1167,7 +1167,7 @@ public void TestAsPublicInterfaceImplementation() VerifySyntax( Generator.AsPublicInterfaceImplementation( - Generator.IndexerDeclaration(parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("a")) }, type: Generator.IdentifierName("t"), accessibility: Accessibility.Internal, modifiers: DeclarationModifiers.Abstract), + Generator.IndexerDeclaration(parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("a"))], type: Generator.IdentifierName("t"), accessibility: Accessibility.Internal, modifiers: DeclarationModifiers.Abstract), Generator.IdentifierName("i")), "public t this[a p]\r\n{\r\n get\r\n {\r\n }\r\n\r\n set\r\n {\r\n }\r\n}"); @@ -1470,7 +1470,7 @@ public void TestAsPrivateInterfaceImplementation() VerifySyntax( Generator.AsPrivateInterfaceImplementation( - Generator.IndexerDeclaration(parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("a")) }, type: Generator.IdentifierName("t"), accessibility: Accessibility.Protected, modifiers: DeclarationModifiers.Abstract), + Generator.IndexerDeclaration(parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("a"))], type: Generator.IdentifierName("t"), accessibility: Accessibility.Protected, modifiers: DeclarationModifiers.Abstract), Generator.IdentifierName("i")), "t i.this[a p]\r\n{\r\n get\r\n {\r\n }\r\n\r\n set\r\n {\r\n }\r\n}"); @@ -1522,7 +1522,7 @@ public void TestClassDeclarations() "class c\r\n{\r\n}"); VerifySyntax( - Generator.ClassDeclaration("c", typeParameters: new[] { "x", "y" }), + Generator.ClassDeclaration("c", typeParameters: ["x", "y"]), "class c\r\n{\r\n}"); VerifySyntax( @@ -1530,11 +1530,11 @@ public void TestClassDeclarations() "class c : x\r\n{\r\n}"); VerifySyntax( - Generator.ClassDeclaration("c", interfaceTypes: new[] { Generator.IdentifierName("x") }), + Generator.ClassDeclaration("c", interfaceTypes: [Generator.IdentifierName("x")]), "class c : x\r\n{\r\n}"); VerifySyntax( - Generator.ClassDeclaration("c", baseType: Generator.IdentifierName("x"), interfaceTypes: new[] { Generator.IdentifierName("y") }), + Generator.ClassDeclaration("c", baseType: Generator.IdentifierName("x"), interfaceTypes: [Generator.IdentifierName("y")]), "class c : x, y\r\n{\r\n}"); VerifySyntax( @@ -1542,15 +1542,15 @@ public void TestClassDeclarations() "class c\r\n{\r\n}"); VerifySyntax( - Generator.ClassDeclaration("c", members: new[] { Generator.FieldDeclaration("y", type: Generator.IdentifierName("x")) }), + Generator.ClassDeclaration("c", members: [Generator.FieldDeclaration("y", type: Generator.IdentifierName("x"))]), "class c\r\n{\r\n x y;\r\n}"); VerifySyntax( - Generator.ClassDeclaration("c", members: new[] { Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("t")) }), + Generator.ClassDeclaration("c", members: [Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("t"))]), "class c\r\n{\r\n t m()\r\n {\r\n }\r\n}"); VerifySyntax( - Generator.ClassDeclaration("c", members: new[] { Generator.ConstructorDeclaration() }), + Generator.ClassDeclaration("c", members: [Generator.ConstructorDeclaration()]), "class c\r\n{\r\n c()\r\n {\r\n }\r\n}"); } @@ -1562,15 +1562,15 @@ public void TestStructDeclarations() "struct s\r\n{\r\n}"); VerifySyntax( - Generator.StructDeclaration("s", typeParameters: new[] { "x", "y" }), + Generator.StructDeclaration("s", typeParameters: ["x", "y"]), "struct s\r\n{\r\n}"); VerifySyntax( - Generator.StructDeclaration("s", interfaceTypes: new[] { Generator.IdentifierName("x") }), + Generator.StructDeclaration("s", interfaceTypes: [Generator.IdentifierName("x")]), "struct s : x\r\n{\r\n}"); VerifySyntax( - Generator.StructDeclaration("s", interfaceTypes: new[] { Generator.IdentifierName("x"), Generator.IdentifierName("y") }), + Generator.StructDeclaration("s", interfaceTypes: [Generator.IdentifierName("x"), Generator.IdentifierName("y")]), "struct s : x, y\r\n{\r\n}"); VerifySyntax( @@ -1578,15 +1578,15 @@ public void TestStructDeclarations() "struct s\r\n{\r\n}"); VerifySyntax( - Generator.StructDeclaration("s", members: new[] { Generator.FieldDeclaration("y", Generator.IdentifierName("x")) }), + Generator.StructDeclaration("s", members: [Generator.FieldDeclaration("y", Generator.IdentifierName("x"))]), "struct s\r\n{\r\n x y;\r\n}"); VerifySyntax( - Generator.StructDeclaration("s", members: new[] { Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("t")) }), + Generator.StructDeclaration("s", members: [Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("t"))]), "struct s\r\n{\r\n t m()\r\n {\r\n }\r\n}"); VerifySyntax( - Generator.StructDeclaration("s", members: new[] { Generator.ConstructorDeclaration("xxx") }), + Generator.StructDeclaration("s", members: [Generator.ConstructorDeclaration("xxx")]), "struct s\r\n{\r\n s()\r\n {\r\n }\r\n}"); } @@ -1598,15 +1598,15 @@ public void TestInterfaceDeclarations() "interface i\r\n{\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", typeParameters: new[] { "x", "y" }), + Generator.InterfaceDeclaration("i", typeParameters: ["x", "y"]), "interface i\r\n{\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", interfaceTypes: new[] { Generator.IdentifierName("a") }), + Generator.InterfaceDeclaration("i", interfaceTypes: [Generator.IdentifierName("a")]), "interface i : a\r\n{\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", interfaceTypes: new[] { Generator.IdentifierName("a"), Generator.IdentifierName("b") }), + Generator.InterfaceDeclaration("i", interfaceTypes: [Generator.IdentifierName("a"), Generator.IdentifierName("b")]), "interface i : a, b\r\n{\r\n}"); VerifySyntax( @@ -1614,35 +1614,35 @@ public void TestInterfaceDeclarations() "interface i\r\n{\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Sealed) }), + Generator.InterfaceDeclaration("i", members: [Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Sealed)]), "interface i\r\n{\r\n t m();\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Sealed) }), + Generator.InterfaceDeclaration("i", members: [Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Sealed)]), "interface i\r\n{\r\n t p { get; set; }\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.ReadOnly) }), + Generator.InterfaceDeclaration("i", members: [Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.ReadOnly)]), "interface i\r\n{\r\n t p { get; }\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("y", Generator.IdentifierName("x")) }, Generator.IdentifierName("t"), Accessibility.Public, DeclarationModifiers.Sealed) }), + Generator.InterfaceDeclaration("i", members: [Generator.IndexerDeclaration([Generator.ParameterDeclaration("y", Generator.IdentifierName("x"))], Generator.IdentifierName("t"), Accessibility.Public, DeclarationModifiers.Sealed)]), "interface i\r\n{\r\n t this[x y] { get; set; }\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("y", Generator.IdentifierName("x")) }, Generator.IdentifierName("t"), Accessibility.Public, DeclarationModifiers.ReadOnly) }), + Generator.InterfaceDeclaration("i", members: [Generator.IndexerDeclaration([Generator.ParameterDeclaration("y", Generator.IdentifierName("x"))], Generator.IdentifierName("t"), Accessibility.Public, DeclarationModifiers.ReadOnly)]), "interface i\r\n{\r\n t this[x y] { get; }\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.CustomEventDeclaration("ep", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Static) }), + Generator.InterfaceDeclaration("i", members: [Generator.CustomEventDeclaration("ep", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Static)]), "interface i\r\n{\r\n event t ep;\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.EventDeclaration("ef", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Static) }), + Generator.InterfaceDeclaration("i", members: [Generator.EventDeclaration("ef", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Static)]), "interface i\r\n{\r\n event t ef;\r\n}"); VerifySyntax( - Generator.InterfaceDeclaration("i", members: new[] { Generator.FieldDeclaration("f", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Sealed) }), + Generator.InterfaceDeclaration("i", members: [Generator.FieldDeclaration("f", Generator.IdentifierName("t"), accessibility: Accessibility.Public, modifiers: DeclarationModifiers.Sealed)]), "interface i\r\n{\r\n t f { get; set; }\r\n}"); } @@ -1668,19 +1668,19 @@ public void TestEnumDeclarations() "enum e\r\n{\r\n}"); VerifySyntax( - Generator.EnumDeclaration("e", members: new[] { Generator.EnumMember("a"), Generator.EnumMember("b"), Generator.EnumMember("c") }), + Generator.EnumDeclaration("e", members: [Generator.EnumMember("a"), Generator.EnumMember("b"), Generator.EnumMember("c")]), "enum e\r\n{\r\n a,\r\n b,\r\n c\r\n}"); VerifySyntax( - Generator.EnumDeclaration("e", members: new[] { Generator.IdentifierName("a"), Generator.EnumMember("b"), Generator.IdentifierName("c") }), + Generator.EnumDeclaration("e", members: [Generator.IdentifierName("a"), Generator.EnumMember("b"), Generator.IdentifierName("c")]), "enum e\r\n{\r\n a,\r\n b,\r\n c\r\n}"); VerifySyntax( - Generator.EnumDeclaration("e", members: new[] { Generator.EnumMember("a", Generator.LiteralExpression(0)), Generator.EnumMember("b"), Generator.EnumMember("c", Generator.LiteralExpression(5)) }), + Generator.EnumDeclaration("e", members: [Generator.EnumMember("a", Generator.LiteralExpression(0)), Generator.EnumMember("b"), Generator.EnumMember("c", Generator.LiteralExpression(5))]), "enum e\r\n{\r\n a = 0,\r\n b,\r\n c = 5\r\n}"); VerifySyntax( - Generator.EnumDeclaration("e", members: new[] { Generator.FieldDeclaration("a", Generator.IdentifierName("e"), initializer: Generator.LiteralExpression(1)) }), + Generator.EnumDeclaration("e", members: [Generator.FieldDeclaration("a", Generator.IdentifierName("e"), initializer: Generator.LiteralExpression(1))]), "enum e\r\n{\r\n a = 1\r\n}"); } @@ -1696,7 +1696,7 @@ public void TestDelegateDeclarations() "delegate t d();"); VerifySyntax( - Generator.DelegateDeclaration("d", returnType: Generator.IdentifierName("t"), parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("pt")) }), + Generator.DelegateDeclaration("d", returnType: Generator.IdentifierName("t"), parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("pt"))]), "delegate t d(pt p);"); VerifySyntax( @@ -1712,7 +1712,7 @@ public void TestDelegateDeclarations() "new delegate void d();"); VerifySyntax( - Generator.DelegateDeclaration("d", typeParameters: new[] { "T", "S" }), + Generator.DelegateDeclaration("d", typeParameters: ["T", "S"]), "delegate void d();"); } @@ -1803,23 +1803,23 @@ public void TestAttributeDeclarations() "[a.b]"); VerifySyntax( - Generator.Attribute("a", new SyntaxNode[] { }), + Generator.Attribute("a", []), "[a()]"); VerifySyntax( - Generator.Attribute("a", new[] { Generator.IdentifierName("x") }), + Generator.Attribute("a", [Generator.IdentifierName("x")]), "[a(x)]"); VerifySyntax( - Generator.Attribute("a", new[] { Generator.AttributeArgument(Generator.IdentifierName("x")) }), + Generator.Attribute("a", [Generator.AttributeArgument(Generator.IdentifierName("x"))]), "[a(x)]"); VerifySyntax( - Generator.Attribute("a", new[] { Generator.AttributeArgument("x", Generator.IdentifierName("y")) }), + Generator.Attribute("a", [Generator.AttributeArgument("x", Generator.IdentifierName("y"))]), "[a(x = y)]"); VerifySyntax( - Generator.Attribute("a", new[] { Generator.IdentifierName("x"), Generator.IdentifierName("y") }), + Generator.Attribute("a", [Generator.IdentifierName("x"), Generator.IdentifierName("y")]), "[a(x, y)]"); } @@ -1860,7 +1860,7 @@ public void TestAddAttributes() VerifySyntax( Generator.AddAttributes( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("z", Generator.IdentifierName("y")) }, Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("z", Generator.IdentifierName("y"))], Generator.IdentifierName("x"), modifiers: DeclarationModifiers.Abstract), Generator.Attribute("a")), "[a]\r\nabstract x this[y z] { get; set; }"); @@ -2733,34 +2733,34 @@ public class C [Fact] public void TestAddMembers() { - AssertMemberNamesEqual("m", Generator.AddMembers(Generator.ClassDeclaration("d"), new[] { Generator.MethodDeclaration("m") })); - AssertMemberNamesEqual("m", Generator.AddMembers(Generator.StructDeclaration("s"), new[] { Generator.MethodDeclaration("m") })); - AssertMemberNamesEqual("m", Generator.AddMembers(Generator.InterfaceDeclaration("i"), new[] { Generator.MethodDeclaration("m") })); - AssertMemberNamesEqual("v", Generator.AddMembers(Generator.EnumDeclaration("e"), new[] { Generator.EnumMember("v") })); - AssertMemberNamesEqual("n2", Generator.AddMembers(Generator.NamespaceDeclaration("n"), new[] { Generator.NamespaceDeclaration("n2") })); - AssertMemberNamesEqual("n", Generator.AddMembers(Generator.CompilationUnit(), new[] { Generator.NamespaceDeclaration("n") })); + AssertMemberNamesEqual("m", Generator.AddMembers(Generator.ClassDeclaration("d"), [Generator.MethodDeclaration("m")])); + AssertMemberNamesEqual("m", Generator.AddMembers(Generator.StructDeclaration("s"), [Generator.MethodDeclaration("m")])); + AssertMemberNamesEqual("m", Generator.AddMembers(Generator.InterfaceDeclaration("i"), [Generator.MethodDeclaration("m")])); + AssertMemberNamesEqual("v", Generator.AddMembers(Generator.EnumDeclaration("e"), [Generator.EnumMember("v")])); + AssertMemberNamesEqual("n2", Generator.AddMembers(Generator.NamespaceDeclaration("n"), [Generator.NamespaceDeclaration("n2")])); + AssertMemberNamesEqual("n", Generator.AddMembers(Generator.CompilationUnit(), [Generator.NamespaceDeclaration("n")])); - AssertMemberNamesEqual(new[] { "m", "m2" }, Generator.AddMembers(Generator.ClassDeclaration("d", members: new[] { Generator.MethodDeclaration("m") }), new[] { Generator.MethodDeclaration("m2") })); - AssertMemberNamesEqual(new[] { "m", "m2" }, Generator.AddMembers(Generator.StructDeclaration("s", members: new[] { Generator.MethodDeclaration("m") }), new[] { Generator.MethodDeclaration("m2") })); - AssertMemberNamesEqual(new[] { "m", "m2" }, Generator.AddMembers(Generator.InterfaceDeclaration("i", members: new[] { Generator.MethodDeclaration("m") }), new[] { Generator.MethodDeclaration("m2") })); - AssertMemberNamesEqual(new[] { "v", "v2" }, Generator.AddMembers(Generator.EnumDeclaration("i", members: new[] { Generator.EnumMember("v") }), new[] { Generator.EnumMember("v2") })); - AssertMemberNamesEqual(new[] { "n1", "n2" }, Generator.AddMembers(Generator.NamespaceDeclaration("n", new[] { Generator.NamespaceDeclaration("n1") }), new[] { Generator.NamespaceDeclaration("n2") })); - AssertMemberNamesEqual(new[] { "n1", "n2" }, Generator.AddMembers(Generator.CompilationUnit(declarations: new[] { Generator.NamespaceDeclaration("n1") }), new[] { Generator.NamespaceDeclaration("n2") })); + AssertMemberNamesEqual(new[] { "m", "m2" }, Generator.AddMembers(Generator.ClassDeclaration("d", members: [Generator.MethodDeclaration("m")]), [Generator.MethodDeclaration("m2")])); + AssertMemberNamesEqual(new[] { "m", "m2" }, Generator.AddMembers(Generator.StructDeclaration("s", members: [Generator.MethodDeclaration("m")]), [Generator.MethodDeclaration("m2")])); + AssertMemberNamesEqual(new[] { "m", "m2" }, Generator.AddMembers(Generator.InterfaceDeclaration("i", members: [Generator.MethodDeclaration("m")]), [Generator.MethodDeclaration("m2")])); + AssertMemberNamesEqual(new[] { "v", "v2" }, Generator.AddMembers(Generator.EnumDeclaration("i", members: [Generator.EnumMember("v")]), [Generator.EnumMember("v2")])); + AssertMemberNamesEqual(new[] { "n1", "n2" }, Generator.AddMembers(Generator.NamespaceDeclaration("n", [Generator.NamespaceDeclaration("n1")]), [Generator.NamespaceDeclaration("n2")])); + AssertMemberNamesEqual(new[] { "n1", "n2" }, Generator.AddMembers(Generator.CompilationUnit(declarations: [Generator.NamespaceDeclaration("n1")]), [Generator.NamespaceDeclaration("n2")])); } [Fact] public void TestRemoveMembers() { // remove all members - TestRemoveAllMembers(Generator.ClassDeclaration("c", members: new[] { Generator.MethodDeclaration("m") })); - TestRemoveAllMembers(Generator.StructDeclaration("s", members: new[] { Generator.MethodDeclaration("m") })); - TestRemoveAllMembers(Generator.InterfaceDeclaration("i", members: new[] { Generator.MethodDeclaration("m") })); - TestRemoveAllMembers(Generator.EnumDeclaration("i", members: new[] { Generator.EnumMember("v") })); - TestRemoveAllMembers(Generator.NamespaceDeclaration("n", new[] { Generator.NamespaceDeclaration("n") })); - TestRemoveAllMembers(Generator.CompilationUnit(declarations: new[] { Generator.NamespaceDeclaration("n") })); + TestRemoveAllMembers(Generator.ClassDeclaration("c", members: [Generator.MethodDeclaration("m")])); + TestRemoveAllMembers(Generator.StructDeclaration("s", members: [Generator.MethodDeclaration("m")])); + TestRemoveAllMembers(Generator.InterfaceDeclaration("i", members: [Generator.MethodDeclaration("m")])); + TestRemoveAllMembers(Generator.EnumDeclaration("i", members: [Generator.EnumMember("v")])); + TestRemoveAllMembers(Generator.NamespaceDeclaration("n", [Generator.NamespaceDeclaration("n")])); + TestRemoveAllMembers(Generator.CompilationUnit(declarations: [Generator.NamespaceDeclaration("n")])); - TestRemoveMember(Generator.ClassDeclaration("c", members: new[] { Generator.MethodDeclaration("m1"), Generator.MethodDeclaration("m2") }), "m1", ["m2"]); - TestRemoveMember(Generator.StructDeclaration("s", members: new[] { Generator.MethodDeclaration("m1"), Generator.MethodDeclaration("m2") }), "m1", ["m2"]); + TestRemoveMember(Generator.ClassDeclaration("c", members: [Generator.MethodDeclaration("m1"), Generator.MethodDeclaration("m2")]), "m1", ["m2"]); + TestRemoveMember(Generator.StructDeclaration("s", members: [Generator.MethodDeclaration("m1"), Generator.MethodDeclaration("m2")]), "m1", ["m2"]); } private void TestRemoveAllMembers(SyntaxNode declaration) @@ -2775,12 +2775,12 @@ private void TestRemoveMember(SyntaxNode declaration, string name, string[] rema [Fact] public void TestGetMembers() { - AssertMemberNamesEqual("m", Generator.ClassDeclaration("c", members: new[] { Generator.MethodDeclaration("m") })); - AssertMemberNamesEqual("m", Generator.StructDeclaration("s", members: new[] { Generator.MethodDeclaration("m") })); - AssertMemberNamesEqual("m", Generator.InterfaceDeclaration("i", members: new[] { Generator.MethodDeclaration("m") })); - AssertMemberNamesEqual("v", Generator.EnumDeclaration("e", members: new[] { Generator.EnumMember("v") })); - AssertMemberNamesEqual("c", Generator.NamespaceDeclaration("n", declarations: new[] { Generator.ClassDeclaration("c") })); - AssertMemberNamesEqual("c", Generator.CompilationUnit(declarations: new[] { Generator.ClassDeclaration("c") })); + AssertMemberNamesEqual("m", Generator.ClassDeclaration("c", members: [Generator.MethodDeclaration("m")])); + AssertMemberNamesEqual("m", Generator.StructDeclaration("s", members: [Generator.MethodDeclaration("m")])); + AssertMemberNamesEqual("m", Generator.InterfaceDeclaration("i", members: [Generator.MethodDeclaration("m")])); + AssertMemberNamesEqual("v", Generator.EnumDeclaration("e", members: [Generator.EnumMember("v")])); + AssertMemberNamesEqual("c", Generator.NamespaceDeclaration("n", declarations: [Generator.ClassDeclaration("c")])); + AssertMemberNamesEqual("c", Generator.CompilationUnit(declarations: [Generator.ClassDeclaration("c")])); } [Fact] @@ -2796,7 +2796,7 @@ public void TestGetDeclarationKind() Assert.Equal(DeclarationKind.Constructor, Generator.GetDeclarationKind(Generator.ConstructorDeclaration())); Assert.Equal(DeclarationKind.Parameter, Generator.GetDeclarationKind(Generator.ParameterDeclaration("p"))); Assert.Equal(DeclarationKind.Property, Generator.GetDeclarationKind(Generator.PropertyDeclaration("p", Generator.IdentifierName("t")))); - Assert.Equal(DeclarationKind.Indexer, Generator.GetDeclarationKind(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t")))); + Assert.Equal(DeclarationKind.Indexer, Generator.GetDeclarationKind(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t")))); Assert.Equal(DeclarationKind.Field, Generator.GetDeclarationKind(Generator.FieldDeclaration("f", Generator.IdentifierName("t")))); Assert.Equal(DeclarationKind.EnumMember, Generator.GetDeclarationKind(Generator.EnumMember("v"))); Assert.Equal(DeclarationKind.Event, Generator.GetDeclarationKind(Generator.EventDeclaration("ef", Generator.IdentifierName("t")))); @@ -2819,7 +2819,7 @@ public void TestGetName() Assert.Equal("", Generator.GetName(Generator.ConstructorDeclaration())); Assert.Equal("p", Generator.GetName(Generator.ParameterDeclaration("p"))); Assert.Equal("p", Generator.GetName(Generator.PropertyDeclaration("p", Generator.IdentifierName("t")))); - Assert.Equal("", Generator.GetName(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t")))); + Assert.Equal("", Generator.GetName(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t")))); Assert.Equal("f", Generator.GetName(Generator.FieldDeclaration("f", Generator.IdentifierName("t")))); Assert.Equal("v", Generator.GetName(Generator.EnumMember("v"))); Assert.Equal("ef", Generator.GetName(Generator.EventDeclaration("ef", Generator.IdentifierName("t")))); @@ -2842,7 +2842,7 @@ public void TestWithName() Assert.Equal("", Generator.GetName(Generator.WithName(Generator.ConstructorDeclaration(), ".ctor"))); Assert.Equal("p", Generator.GetName(Generator.WithName(Generator.ParameterDeclaration("x"), "p"))); Assert.Equal("p", Generator.GetName(Generator.WithName(Generator.PropertyDeclaration("x", Generator.IdentifierName("t")), "p"))); - Assert.Equal("", Generator.GetName(Generator.WithName(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t")), "this"))); + Assert.Equal("", Generator.GetName(Generator.WithName(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t")), "this"))); Assert.Equal("f", Generator.GetName(Generator.WithName(Generator.FieldDeclaration("x", Generator.IdentifierName("t")), "f"))); Assert.Equal("v", Generator.GetName(Generator.WithName(Generator.EnumMember("x"), "v"))); Assert.Equal("ef", Generator.GetName(Generator.WithName(Generator.EventDeclaration("x", Generator.IdentifierName("t")), "ef"))); @@ -2865,7 +2865,7 @@ public void TestGetAccessibility() Assert.Equal(Accessibility.Internal, Generator.GetAccessibility(Generator.ConstructorDeclaration(accessibility: Accessibility.Internal))); Assert.Equal(Accessibility.NotApplicable, Generator.GetAccessibility(Generator.ParameterDeclaration("p"))); Assert.Equal(Accessibility.Internal, Generator.GetAccessibility(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), accessibility: Accessibility.Internal))); - Assert.Equal(Accessibility.Internal, Generator.GetAccessibility(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t"), accessibility: Accessibility.Internal))); + Assert.Equal(Accessibility.Internal, Generator.GetAccessibility(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t"), accessibility: Accessibility.Internal))); Assert.Equal(Accessibility.Internal, Generator.GetAccessibility(Generator.FieldDeclaration("f", Generator.IdentifierName("t"), accessibility: Accessibility.Internal))); Assert.Equal(Accessibility.NotApplicable, Generator.GetAccessibility(Generator.EnumMember("v"))); Assert.Equal(Accessibility.Internal, Generator.GetAccessibility(Generator.EventDeclaration("ef", Generator.IdentifierName("t"), accessibility: Accessibility.Internal))); @@ -2889,7 +2889,7 @@ public void TestWithAccessibility() Assert.Equal(Accessibility.Private, Generator.GetAccessibility(Generator.WithAccessibility(Generator.ConstructorDeclaration(accessibility: Accessibility.Internal), Accessibility.Private))); Assert.Equal(Accessibility.NotApplicable, Generator.GetAccessibility(Generator.WithAccessibility(Generator.ParameterDeclaration("p"), Accessibility.Private))); Assert.Equal(Accessibility.Private, Generator.GetAccessibility(Generator.WithAccessibility(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), accessibility: Accessibility.Internal), Accessibility.Private))); - Assert.Equal(Accessibility.Private, Generator.GetAccessibility(Generator.WithAccessibility(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t"), accessibility: Accessibility.Internal), Accessibility.Private))); + Assert.Equal(Accessibility.Private, Generator.GetAccessibility(Generator.WithAccessibility(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t"), accessibility: Accessibility.Internal), Accessibility.Private))); Assert.Equal(Accessibility.Private, Generator.GetAccessibility(Generator.WithAccessibility(Generator.FieldDeclaration("f", Generator.IdentifierName("t"), accessibility: Accessibility.Internal), Accessibility.Private))); Assert.Equal(Accessibility.NotApplicable, Generator.GetAccessibility(Generator.WithAccessibility(Generator.EnumMember("v"), Accessibility.Private))); Assert.Equal(Accessibility.Private, Generator.GetAccessibility(Generator.WithAccessibility(Generator.EventDeclaration("ef", Generator.IdentifierName("t"), accessibility: Accessibility.Internal), Accessibility.Private))); @@ -2913,7 +2913,7 @@ public void TestGetModifiers() Assert.Equal(DeclarationModifiers.Static, Generator.GetModifiers(Generator.ConstructorDeclaration(modifiers: DeclarationModifiers.Static))); Assert.Equal(DeclarationModifiers.None, Generator.GetModifiers(Generator.ParameterDeclaration("p"))); Assert.Equal(DeclarationModifiers.Abstract, Generator.GetModifiers(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), modifiers: DeclarationModifiers.Abstract))); - Assert.Equal(DeclarationModifiers.Abstract, Generator.GetModifiers(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t"), modifiers: DeclarationModifiers.Abstract))); + Assert.Equal(DeclarationModifiers.Abstract, Generator.GetModifiers(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t"), modifiers: DeclarationModifiers.Abstract))); Assert.Equal(DeclarationModifiers.Const, Generator.GetModifiers(Generator.FieldDeclaration("f", Generator.IdentifierName("t"), modifiers: DeclarationModifiers.Const))); Assert.Equal(DeclarationModifiers.Static, Generator.GetModifiers(Generator.EventDeclaration("ef", Generator.IdentifierName("t"), modifiers: DeclarationModifiers.Static))); Assert.Equal(DeclarationModifiers.Static, Generator.GetModifiers(Generator.CustomEventDeclaration("ep", Generator.IdentifierName("t"), modifiers: DeclarationModifiers.Static))); @@ -2936,7 +2936,7 @@ public void TestWithModifiers() Assert.Equal(DeclarationModifiers.Static, Generator.GetModifiers(Generator.WithModifiers(Generator.ConstructorDeclaration(), DeclarationModifiers.Static))); Assert.Equal(DeclarationModifiers.None, Generator.GetModifiers(Generator.WithModifiers(Generator.ParameterDeclaration("p"), DeclarationModifiers.Abstract))); Assert.Equal(DeclarationModifiers.Abstract, Generator.GetModifiers(Generator.WithModifiers(Generator.PropertyDeclaration("p", Generator.IdentifierName("t")), DeclarationModifiers.Abstract))); - Assert.Equal(DeclarationModifiers.Abstract, Generator.GetModifiers(Generator.WithModifiers(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t")), DeclarationModifiers.Abstract))); + Assert.Equal(DeclarationModifiers.Abstract, Generator.GetModifiers(Generator.WithModifiers(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t")), DeclarationModifiers.Abstract))); Assert.Equal(DeclarationModifiers.Const, Generator.GetModifiers(Generator.WithModifiers(Generator.FieldDeclaration("f", Generator.IdentifierName("t")), DeclarationModifiers.Const))); Assert.Equal(DeclarationModifiers.Static, Generator.GetModifiers(Generator.WithModifiers(Generator.EventDeclaration("ef", Generator.IdentifierName("t")), DeclarationModifiers.Static))); Assert.Equal(DeclarationModifiers.Static, Generator.GetModifiers(Generator.WithModifiers(Generator.CustomEventDeclaration("ep", Generator.IdentifierName("t")), DeclarationModifiers.Static))); @@ -2995,7 +2995,7 @@ public void TestWithModifiers_AllowedModifiers() Assert.Equal( DeclarationModifiers.Abstract | DeclarationModifiers.New | DeclarationModifiers.Override | DeclarationModifiers.ReadOnly | DeclarationModifiers.Sealed | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.Unsafe, - Generator.GetModifiers(Generator.WithModifiers(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("i") }, Generator.IdentifierName("t")), allModifiers))); + Generator.GetModifiers(Generator.WithModifiers(Generator.IndexerDeclaration([Generator.ParameterDeclaration("i")], Generator.IdentifierName("t")), allModifiers))); Assert.Equal( DeclarationModifiers.Abstract | DeclarationModifiers.New | DeclarationModifiers.Override | DeclarationModifiers.Sealed | DeclarationModifiers.Static | DeclarationModifiers.Virtual | DeclarationModifiers.Unsafe | DeclarationModifiers.ReadOnly, @@ -3112,7 +3112,7 @@ public void TestGetType() Assert.Equal("t", Generator.GetType(Generator.FieldDeclaration("f", Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"))).ToString()); - Assert.Equal("t", Generator.GetType(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("pt")) }, Generator.IdentifierName("t"))).ToString()); + Assert.Equal("t", Generator.GetType(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("pt"))], Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.EventDeclaration("ef", Generator.IdentifierName("t"))).ToString()); @@ -3133,7 +3133,7 @@ public void TestWithType() Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.MethodDeclaration("m", returnType: Generator.IdentifierName("x")), Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.FieldDeclaration("f", Generator.IdentifierName("x")), Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.PropertyDeclaration("p", Generator.IdentifierName("x")), Generator.IdentifierName("t"))).ToString()); - Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("pt")) }, Generator.IdentifierName("x")), Generator.IdentifierName("t"))).ToString()); + Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("pt"))], Generator.IdentifierName("x")), Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.ParameterDeclaration("p", Generator.IdentifierName("x")), Generator.IdentifierName("t"))).ToString()); Assert.Equal("t", Generator.GetType(Generator.WithType(Generator.DelegateDeclaration("t"), Generator.IdentifierName("t"))).ToString()); @@ -3150,15 +3150,15 @@ public void TestWithType() public void TestGetParameters() { Assert.Equal(0, Generator.GetParameters(Generator.MethodDeclaration("m")).Count); - Assert.Equal(1, Generator.GetParameters(Generator.MethodDeclaration("m", parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(2, Generator.GetParameters(Generator.MethodDeclaration("m", parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")), Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2")) })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.MethodDeclaration("m", parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(2, Generator.GetParameters(Generator.MethodDeclaration("m", parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("t")), Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2"))])).Count); Assert.Equal(0, Generator.GetParameters(Generator.ConstructorDeclaration()).Count); - Assert.Equal(1, Generator.GetParameters(Generator.ConstructorDeclaration(parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(2, Generator.GetParameters(Generator.ConstructorDeclaration(parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")), Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2")) })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.ConstructorDeclaration(parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(2, Generator.GetParameters(Generator.ConstructorDeclaration(parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("t")), Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2"))])).Count); - Assert.Equal(1, Generator.GetParameters(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }, Generator.IdentifierName("t"))).Count); - Assert.Equal(2, Generator.GetParameters(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")), Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2")) }, Generator.IdentifierName("t"))).Count); + Assert.Equal(1, Generator.GetParameters(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))], Generator.IdentifierName("t"))).Count); + Assert.Equal(2, Generator.GetParameters(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("t")), Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2"))], Generator.IdentifierName("t"))).Count); Assert.Equal(0, Generator.GetParameters(Generator.ValueReturningLambdaExpression(Generator.IdentifierName("expr"))).Count); Assert.Equal(1, Generator.GetParameters(Generator.ValueReturningLambdaExpression("p1", Generator.IdentifierName("expr"))).Count); @@ -3167,7 +3167,7 @@ public void TestGetParameters() Assert.Equal(1, Generator.GetParameters(Generator.VoidReturningLambdaExpression("p1", Generator.IdentifierName("expr"))).Count); Assert.Equal(0, Generator.GetParameters(Generator.DelegateDeclaration("d")).Count); - Assert.Equal(1, Generator.GetParameters(Generator.DelegateDeclaration("d", parameters: new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.DelegateDeclaration("d", parameters: [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); Assert.Equal(0, Generator.GetParameters(Generator.ClassDeclaration("c")).Count); Assert.Equal(0, Generator.GetParameters(Generator.IdentifierName("x")).Count); @@ -3176,19 +3176,19 @@ public void TestGetParameters() [Fact] public void TestAddParameters() { - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.MethodDeclaration("m"), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.ConstructorDeclaration(), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(3, Generator.GetParameters(Generator.AddParameters(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }, Generator.IdentifierName("t")), new[] { Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2")), Generator.ParameterDeclaration("p3", Generator.IdentifierName("t3")) })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.MethodDeclaration("m"), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.ConstructorDeclaration(), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(3, Generator.GetParameters(Generator.AddParameters(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))], Generator.IdentifierName("t")), [Generator.ParameterDeclaration("p2", Generator.IdentifierName("t2")), Generator.ParameterDeclaration("p3", Generator.IdentifierName("t3"))])).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.ValueReturningLambdaExpression(Generator.IdentifierName("expr")), new[] { Generator.LambdaParameter("p") })).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.VoidReturningLambdaExpression(Generator.IdentifierName("expr")), new[] { Generator.LambdaParameter("p") })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.ValueReturningLambdaExpression(Generator.IdentifierName("expr")), [Generator.LambdaParameter("p")])).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.VoidReturningLambdaExpression(Generator.IdentifierName("expr")), [Generator.LambdaParameter("p")])).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.DelegateDeclaration("d"), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.DelegateDeclaration("d"), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.ClassDeclaration("c"), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.StructDeclaration("c"), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.InterfaceDeclaration("c"), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); - Assert.Equal(0, Generator.GetParameters(Generator.AddParameters(Generator.IdentifierName("x"), new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) })).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.ClassDeclaration("c"), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.StructDeclaration("c"), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(1, Generator.GetParameters(Generator.AddParameters(Generator.InterfaceDeclaration("c"), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); + Assert.Equal(0, Generator.GetParameters(Generator.AddParameters(Generator.IdentifierName("x"), [Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))])).Count); } [Fact] @@ -3200,8 +3200,8 @@ public void TestGetExpression() Assert.Equal("x", Generator.GetExpression(Generator.LocalDeclarationStatement("loc", initializer: Generator.IdentifierName("x"))).ToString()); // lambda bodies - Assert.Null(Generator.GetExpression(Generator.ValueReturningLambdaExpression("p", new[] { Generator.IdentifierName("x") }))); - Assert.Equal(1, Generator.GetStatements(Generator.ValueReturningLambdaExpression("p", new[] { Generator.IdentifierName("x") })).Count); + Assert.Null(Generator.GetExpression(Generator.ValueReturningLambdaExpression("p", [Generator.IdentifierName("x")]))); + Assert.Equal(1, Generator.GetStatements(Generator.ValueReturningLambdaExpression("p", [Generator.IdentifierName("x")])).Count); Assert.Equal("x", Generator.GetExpression(Generator.ValueReturningLambdaExpression(Generator.IdentifierName("x"))).ToString()); Assert.Equal("x", Generator.GetExpression(Generator.VoidReturningLambdaExpression(Generator.IdentifierName("x"))).ToString()); Assert.Equal("x", Generator.GetExpression(Generator.ValueReturningLambdaExpression("p", Generator.IdentifierName("x"))).ToString()); @@ -3234,10 +3234,10 @@ public void TestWithExpression() Assert.Equal("x", Generator.GetExpression(Generator.WithExpression(Generator.LocalDeclarationStatement(Generator.IdentifierName("t"), "loc"), Generator.IdentifierName("x"))).ToString()); // lambda bodies - Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.ValueReturningLambdaExpression("p", new[] { Generator.IdentifierName("x") }), Generator.IdentifierName("y"))).ToString()); - Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.VoidReturningLambdaExpression("p", new[] { Generator.IdentifierName("x") }), Generator.IdentifierName("y"))).ToString()); - Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.ValueReturningLambdaExpression(new[] { Generator.IdentifierName("x") }), Generator.IdentifierName("y"))).ToString()); - Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.VoidReturningLambdaExpression(new[] { Generator.IdentifierName("x") }), Generator.IdentifierName("y"))).ToString()); + Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.ValueReturningLambdaExpression("p", [Generator.IdentifierName("x")]), Generator.IdentifierName("y"))).ToString()); + Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.VoidReturningLambdaExpression("p", [Generator.IdentifierName("x")]), Generator.IdentifierName("y"))).ToString()); + Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.ValueReturningLambdaExpression([Generator.IdentifierName("x")]), Generator.IdentifierName("y"))).ToString()); + Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.VoidReturningLambdaExpression([Generator.IdentifierName("x")]), Generator.IdentifierName("y"))).ToString()); Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.ValueReturningLambdaExpression("p", Generator.IdentifierName("x")), Generator.IdentifierName("y"))).ToString()); Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.VoidReturningLambdaExpression("p", Generator.IdentifierName("x")), Generator.IdentifierName("y"))).ToString()); Assert.Equal("y", Generator.GetExpression(Generator.WithExpression(Generator.ValueReturningLambdaExpression(Generator.IdentifierName("x")), Generator.IdentifierName("y"))).ToString()); @@ -3322,34 +3322,34 @@ public void TestAccessorDeclarations2() VerifySyntax( Generator.WithAccessorDeclarations( Generator.PropertyDeclaration("p", Generator.IdentifierName("x")), - Generator.GetAccessorDeclaration(Accessibility.NotApplicable, new[] { Generator.ReturnStatement() })), + Generator.GetAccessorDeclaration(Accessibility.NotApplicable, [Generator.ReturnStatement()])), "x p\r\n{\r\n get\r\n {\r\n return;\r\n }\r\n}"); VerifySyntax( Generator.WithAccessorDeclarations( Generator.PropertyDeclaration("p", Generator.IdentifierName("x")), - Generator.GetAccessorDeclaration(Accessibility.Protected, new[] { Generator.ReturnStatement() })), + Generator.GetAccessorDeclaration(Accessibility.Protected, [Generator.ReturnStatement()])), "x p\r\n{\r\n protected get\r\n {\r\n return;\r\n }\r\n}"); VerifySyntax( Generator.WithAccessorDeclarations( Generator.PropertyDeclaration("p", Generator.IdentifierName("x")), - Generator.SetAccessorDeclaration(Accessibility.Protected, new[] { Generator.ReturnStatement() })), + Generator.SetAccessorDeclaration(Accessibility.Protected, [Generator.ReturnStatement()])), "x p\r\n{\r\n protected set\r\n {\r\n return;\r\n }\r\n}"); VerifySyntax( - Generator.WithAccessorDeclarations(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }, Generator.IdentifierName("x"))), + Generator.WithAccessorDeclarations(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))], Generator.IdentifierName("x"))), "x this[t p] { }"); VerifySyntax( - Generator.WithAccessorDeclarations(Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }, Generator.IdentifierName("x")), - Generator.GetAccessorDeclaration(Accessibility.Protected, new[] { Generator.ReturnStatement() })), + Generator.WithAccessorDeclarations(Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))], Generator.IdentifierName("x")), + Generator.GetAccessorDeclaration(Accessibility.Protected, [Generator.ReturnStatement()])), "x this[t p]\r\n{\r\n protected get\r\n {\r\n return;\r\n }\r\n}"); VerifySyntax( Generator.WithAccessorDeclarations( - Generator.IndexerDeclaration(new[] { Generator.ParameterDeclaration("p", Generator.IdentifierName("t")) }, Generator.IdentifierName("x")), - Generator.SetAccessorDeclaration(Accessibility.Protected, new[] { Generator.ReturnStatement() })), + Generator.IndexerDeclaration([Generator.ParameterDeclaration("p", Generator.IdentifierName("t"))], Generator.IdentifierName("x")), + Generator.SetAccessorDeclaration(Accessibility.Protected, [Generator.ReturnStatement()])), "x this[t p]\r\n{\r\n protected set\r\n {\r\n return;\r\n }\r\n}"); } @@ -3369,7 +3369,7 @@ public void TestAccessorsOnSpecialProperties() Assert.Equal(0, Generator.GetAccessors(y).Count); // adding accessors to expression value property will not succeed - var y2 = Generator.AddAccessors(y, new[] { Generator.GetAccessor(x, DeclarationKind.GetAccessor) }); + var y2 = Generator.AddAccessors(y, [Generator.GetAccessor(x, DeclarationKind.GetAccessor)]); Assert.NotNull(y2); Assert.Equal(0, Generator.GetAccessors(y2).Count); } @@ -3390,7 +3390,7 @@ public void TestAccessorsOnSpecialIndexers() Assert.Equal(0, Generator.GetAccessors(y).Count); // adding accessors to expression value indexer will not succeed - var y2 = Generator.AddAccessors(y, new[] { Generator.GetAccessor(x, DeclarationKind.GetAccessor) }); + var y2 = Generator.AddAccessors(y, [Generator.GetAccessor(x, DeclarationKind.GetAccessor)]); Assert.NotNull(y2); Assert.Equal(0, Generator.GetAccessors(y2).Count); } @@ -3507,8 +3507,8 @@ public void TestGetAccessorStatements() Assert.Equal(0, Generator.GetGetAccessorStatements(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"))).Count); Assert.Equal(2, Generator.GetGetAccessorStatements(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), getAccessorStatements: stmts)).Count); - Assert.Equal(0, Generator.GetGetAccessorStatements(Generator.IndexerDeclaration(new[] { p }, Generator.IdentifierName("t"))).Count); - Assert.Equal(2, Generator.GetGetAccessorStatements(Generator.IndexerDeclaration(new[] { p }, Generator.IdentifierName("t"), getAccessorStatements: stmts)).Count); + Assert.Equal(0, Generator.GetGetAccessorStatements(Generator.IndexerDeclaration([p], Generator.IdentifierName("t"))).Count); + Assert.Equal(2, Generator.GetGetAccessorStatements(Generator.IndexerDeclaration([p], Generator.IdentifierName("t"), getAccessorStatements: stmts)).Count); Assert.Equal(0, Generator.GetGetAccessorStatements(Generator.IdentifierName("x")).Count); @@ -3516,8 +3516,8 @@ public void TestGetAccessorStatements() Assert.Equal(0, Generator.GetSetAccessorStatements(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"))).Count); Assert.Equal(2, Generator.GetSetAccessorStatements(Generator.PropertyDeclaration("p", Generator.IdentifierName("t"), setAccessorStatements: stmts)).Count); - Assert.Equal(0, Generator.GetSetAccessorStatements(Generator.IndexerDeclaration(new[] { p }, Generator.IdentifierName("t"))).Count); - Assert.Equal(2, Generator.GetSetAccessorStatements(Generator.IndexerDeclaration(new[] { p }, Generator.IdentifierName("t"), setAccessorStatements: stmts)).Count); + Assert.Equal(0, Generator.GetSetAccessorStatements(Generator.IndexerDeclaration([p], Generator.IdentifierName("t"))).Count); + Assert.Equal(2, Generator.GetSetAccessorStatements(Generator.IndexerDeclaration([p], Generator.IdentifierName("t"), setAccessorStatements: stmts)).Count); Assert.Equal(0, Generator.GetSetAccessorStatements(Generator.IdentifierName("x")).Count); } @@ -3538,12 +3538,12 @@ public void TestWithAccessorStatements() // get-accessor Assert.Equal(2, Generator.GetGetAccessorStatements(Generator.WithGetAccessorStatements(Generator.PropertyDeclaration("p", Generator.IdentifierName("t")), stmts)).Count); - Assert.Equal(2, Generator.GetGetAccessorStatements(Generator.WithGetAccessorStatements(Generator.IndexerDeclaration(new[] { p }, Generator.IdentifierName("t")), stmts)).Count); + Assert.Equal(2, Generator.GetGetAccessorStatements(Generator.WithGetAccessorStatements(Generator.IndexerDeclaration([p], Generator.IdentifierName("t")), stmts)).Count); Assert.Equal(0, Generator.GetGetAccessorStatements(Generator.WithGetAccessorStatements(Generator.IdentifierName("x"), stmts)).Count); // set-accessor Assert.Equal(2, Generator.GetSetAccessorStatements(Generator.WithSetAccessorStatements(Generator.PropertyDeclaration("p", Generator.IdentifierName("t")), stmts)).Count); - Assert.Equal(2, Generator.GetSetAccessorStatements(Generator.WithSetAccessorStatements(Generator.IndexerDeclaration(new[] { p }, Generator.IdentifierName("t")), stmts)).Count); + Assert.Equal(2, Generator.GetSetAccessorStatements(Generator.WithSetAccessorStatements(Generator.IndexerDeclaration([p], Generator.IdentifierName("t")), stmts)).Count); Assert.Equal(0, Generator.GetSetAccessorStatements(Generator.WithSetAccessorStatements(Generator.IdentifierName("x"), stmts)).Count); } @@ -3799,7 +3799,7 @@ public void TestMultiFieldDeclarations() }"); VerifySyntax( - Generator.ClassDeclaration("C", members: new[] { declX, declY }), + Generator.ClassDeclaration("C", members: [declX, declY]), @"class C { public static int X; @@ -4060,7 +4060,7 @@ public class C Assert.Equal(SyntaxKind.AttributeList, xNamedQ.Kind()); Assert.Equal("[Q]", xNamedQ.ToString()); - var xWithArg = Generator.AddAttributeArguments(attrX, new[] { Generator.AttributeArgument(Generator.IdentifierName("e")) }); + var xWithArg = Generator.AddAttributeArguments(attrX, [Generator.AttributeArgument(Generator.IdentifierName("e"))]); Assert.Equal(DeclarationKind.Attribute, Generator.GetDeclarationKind(xWithArg)); Assert.Equal(SyntaxKind.AttributeList, xWithArg.Kind()); Assert.Equal("[X(e)]", xWithArg.ToString()); @@ -4102,49 +4102,49 @@ public class C // Removing attributes VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrX }), + Generator.RemoveNodes(declC, [attrX]), @"[Y, Z] public class C { }"); VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrY }), + Generator.RemoveNodes(declC, [attrY]), @"[X, Z] public class C { }"); VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrZ }), + Generator.RemoveNodes(declC, [attrZ]), @"[X, Y] public class C { }"); VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrX, attrY }), + Generator.RemoveNodes(declC, [attrX, attrY]), @"[Z] public class C { }"); VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrX, attrZ }), + Generator.RemoveNodes(declC, [attrX, attrZ]), @"[Y] public class C { }"); VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrY, attrZ }), + Generator.RemoveNodes(declC, [attrY, attrZ]), @"[X] public class C { }"); VerifySyntax( - Generator.RemoveNodes(declC, new[] { attrX, attrY, attrZ }), + Generator.RemoveNodes(declC, [attrX, attrY, attrZ]), @"public class C { }"); @@ -4172,7 +4172,7 @@ public class C }"); VerifySyntax( - Generator.ReplaceNode(declC, attrX, Generator.AddAttributeArguments(attrX, new[] { Generator.AttributeArgument(Generator.IdentifierName("e")) })), + Generator.ReplaceNode(declC, attrX, Generator.AddAttributeArguments(attrX, [Generator.AttributeArgument(Generator.IdentifierName("e"))])), @"[X(e), Y, Z] public class C { @@ -4240,7 +4240,7 @@ public void M() Assert.Equal(SyntaxKind.AttributeList, xNamedQ.Kind()); Assert.Equal("[Q]", xNamedQ.ToString()); - var xWithArg = Generator.AddAttributeArguments(attrX, new[] { Generator.AttributeArgument(Generator.IdentifierName("e")) }); + var xWithArg = Generator.AddAttributeArguments(attrX, [Generator.AttributeArgument(Generator.IdentifierName("e"))]); Assert.Equal(DeclarationKind.Attribute, Generator.GetDeclarationKind(xWithArg)); Assert.Equal(SyntaxKind.AttributeList, xWithArg.Kind()); Assert.Equal("[X(e)]", xWithArg.ToString()); @@ -4289,7 +4289,7 @@ public void M() }"); VerifySyntax( - Generator.ReplaceNode(declM, attrX, Generator.AddAttributeArguments(attrX, new[] { Generator.AttributeArgument(Generator.IdentifierName("e")) })), + Generator.ReplaceNode(declM, attrX, Generator.AddAttributeArguments(attrX, [Generator.AttributeArgument(Generator.IdentifierName("e"))])), @"[return: X(e), Y, Z] public void M() { diff --git a/src/Workspaces/Core/MSBuild.BuildHost/BuildHost.cs b/src/Workspaces/Core/MSBuild.BuildHost/BuildHost.cs index ad895dec25972..f188a353ef30f 100644 --- a/src/Workspaces/Core/MSBuild.BuildHost/BuildHost.cs +++ b/src/Workspaces/Core/MSBuild.BuildHost/BuildHost.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +extern alias workspaces; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -105,7 +106,11 @@ private bool TryEnsureMSBuildLoaded(string projectOrSolutionFilePath) } } +#if NET472 || NET6_0 // If we're compiling against net472 or net6.0, we get our MemberNotNull from the workspaces assembly. It has it in the net6.0 case since we're consuming the netstandard2.0 version of Workspaces. + [workspaces::System.Diagnostics.CodeAnalysis.MemberNotNull(nameof(_buildManager))] +#else // If we're compiling against net7.0 or higher, then we're getting it staright from the framework. [MemberNotNull(nameof(_buildManager))] +#endif [MethodImpl(MethodImplOptions.NoInlining)] // Do not inline this, since this creates MSBuild types which are being loaded by the caller private void CreateBuildManager() { diff --git a/src/Workspaces/Core/MSBuild.BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj b/src/Workspaces/Core/MSBuild.BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj index 9abe5f533521d..063d82e3b829a 100644 --- a/src/Workspaces/Core/MSBuild.BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj +++ b/src/Workspaces/Core/MSBuild.BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj @@ -4,7 +4,7 @@ Exe Microsoft.CodeAnalysis - $(NetRoslynSourceBuild);net472 + $(NetRoslynBuildHostNetCoreVersion);net472 false @@ -22,9 +22,11 @@ AnyCPU - - - + + + + @@ -33,7 +35,14 @@ - + + global,workspaces + + + + + + diff --git a/src/Workspaces/Core/MSBuild/MSBuild/BuildHostProcessManager.cs b/src/Workspaces/Core/MSBuild/MSBuild/BuildHostProcessManager.cs index 3ed2d6dbe8c5d..4c15cdffe1d0a 100644 --- a/src/Workspaces/Core/MSBuild/MSBuild/BuildHostProcessManager.cs +++ b/src/Workspaces/Core/MSBuild/MSBuild/BuildHostProcessManager.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; @@ -96,8 +97,10 @@ public async Task GetBuildHostAsync(BuildHostProcessKind buildH // We've subscribed to Disconnected, but if the process crashed before that point we might have not seen it if (process.HasExited) { + buildHostProcess.LogProcessFailure(); throw new Exception($"BuildHost process exited immediately with {process.ExitCode}"); } + _processes.Add(buildHostKind, buildHostProcess); } @@ -127,7 +130,7 @@ private void BuildHostProcess_Disconnected(object? sender, EventArgs e) // Dispose outside of the lock (even though we don't expect much to happen at this point) if (processToDispose != null) { - processToDispose.LoggerForProcessMessages?.LogTrace("Process exited."); + processToDispose.LogProcessFailure(); await processToDispose.DisposeAsync().ConfigureAwait(false); } }); @@ -328,15 +331,21 @@ public enum BuildHostProcessKind private sealed class BuildHostProcess : IAsyncDisposable { + private readonly ILogger? _logger; private readonly Process _process; private readonly RpcClient _rpcClient; + /// + /// A string builder where we collect the process log messages, in case we do want to know them if the process crashes. + /// Reads/writes should be synchronized by locking this object. + /// + private readonly StringBuilder _processLogMessages = new(); + private int _disposed = 0; public BuildHostProcess(Process process, ILoggerFactory? loggerFactory) { - LoggerForProcessMessages = loggerFactory?.CreateLogger($"BuildHost PID {process.Id}"); - + _logger = loggerFactory?.CreateLogger($"BuildHost PID {process.Id}"); _process = process; _process.EnableRaisingEvents = true; @@ -361,11 +370,15 @@ private void Process_Exited(object? sender, EventArgs e) private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) { if (e.Data is not null) - LoggerForProcessMessages?.LogTrace($"Message from Process: {e.Data}"); + { + lock (_processLogMessages) + _processLogMessages.AppendLine(e.Data); + + _logger?.LogTrace($"Message from Process: {e.Data}"); + } } public RemoteBuildHost BuildHost { get; } - public ILogger? LoggerForProcessMessages { get; } public event EventHandler? Disconnected; @@ -380,23 +393,39 @@ public async ValueTask DisposeAsync() { if (!_process.HasExited) { - LoggerForProcessMessages?.LogTrace("Sending a Shutdown request to the BuildHost."); + _logger?.LogTrace("Sending a Shutdown request to the BuildHost."); await BuildHost.ShutdownAsync(CancellationToken.None).ConfigureAwait(false); } _rpcClient.Shutdown(); - LoggerForProcessMessages?.LogTrace("Process shut down."); + _logger?.LogTrace("Process shut down."); } catch (Exception e) { - LoggerForProcessMessages?.LogError(e, "Exception while shutting down the BuildHost process."); + _logger?.LogError(e, "Exception while shutting down the BuildHost process."); - // OK, process may have gone bad. + // Process may have gone bad, so not much else we can do. + LogProcessFailure(); _process.Kill(); } } + + public void LogProcessFailure() + { + if (_logger == null) + return; + + string processLog; + lock (_processLogMessages) + processLog = _processLogMessages.ToString(); + + if (!_process.HasExited) + _logger.LogError("The BuildHost process is not responding. Process output:{newLine}{processLog}", Environment.NewLine, processLog); + else if (_process.ExitCode != 0) + _logger.LogError("The BuildHost process exited with {errorCode}. Process output:{newLine}{processLog}", _process.ExitCode, Environment.NewLine, processLog); + } } } diff --git a/src/Workspaces/Core/MSBuild/MSBuild/DiagnosticReporterLoggerProvider.cs b/src/Workspaces/Core/MSBuild/MSBuild/DiagnosticReporterLoggerProvider.cs new file mode 100644 index 0000000000000..2f3feaa431f28 --- /dev/null +++ b/src/Workspaces/Core/MSBuild/MSBuild/DiagnosticReporterLoggerProvider.cs @@ -0,0 +1,58 @@ +// 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. + +using System; +using Microsoft.Extensions.Logging; + +namespace Microsoft.CodeAnalysis.MSBuild; + +internal class DiagnosticReporterLoggerProvider : ILoggerProvider +{ + private readonly DiagnosticReporter _reporter; + + private DiagnosticReporterLoggerProvider(DiagnosticReporter reporter) + { + _reporter = reporter; + } + + public ILogger CreateLogger(string categoryName) + { + return new Logger(_reporter, categoryName); + } + + public void Dispose() + { + } + + public static ILoggerFactory CreateLoggerFactoryForDiagnosticReporter(DiagnosticReporter reporter) + { + // Note: it's important we set MinLevel here, or otherwise we'll still get called in Log() for things below LogLevel.Warning. + return new LoggerFactory( + [new DiagnosticReporterLoggerProvider(reporter)], + new LoggerFilterOptions() { MinLevel = LogLevel.Warning }); + } + + private sealed class Logger(DiagnosticReporter reporter, string categoryName) : ILogger + { + public IDisposable? BeginScope(TState state) where TState : notnull + { + return null; + } + + public bool IsEnabled(LogLevel logLevel) + { + return logLevel >= LogLevel.Warning; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) + { + var kind = logLevel == LogLevel.Warning ? WorkspaceDiagnosticKind.Warning : WorkspaceDiagnosticKind.Failure; + var message = formatter(state, exception); + if (!string.IsNullOrEmpty(categoryName)) + message = $"[{categoryName}] {message}"; + + reporter.Report(new WorkspaceDiagnostic(kind, message)); + } + } +} diff --git a/src/Workspaces/Core/MSBuild/MSBuild/MSBuildProjectLoader.cs b/src/Workspaces/Core/MSBuild/MSBuild/MSBuildProjectLoader.cs index 17892051e975c..4487e1f70532f 100644 --- a/src/Workspaces/Core/MSBuild/MSBuild/MSBuildProjectLoader.cs +++ b/src/Workspaces/Core/MSBuild/MSBuild/MSBuildProjectLoader.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using Microsoft.Build.Framework; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.MSBuild.Build; using Roslyn.Utilities; using MSB = Microsoft.Build; @@ -24,6 +23,7 @@ public partial class MSBuildProjectLoader private readonly SolutionServices _solutionServices; private readonly DiagnosticReporter _diagnosticReporter; + private readonly Microsoft.Extensions.Logging.ILoggerFactory _loggerFactory; private readonly PathResolver _pathResolver; private readonly ProjectFileExtensionRegistry _projectFileExtensionRegistry; @@ -33,13 +33,15 @@ public partial class MSBuildProjectLoader internal MSBuildProjectLoader( SolutionServices solutionServices, DiagnosticReporter diagnosticReporter, - ProjectFileExtensionRegistry? projectFileExtensionRegistry, + Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, + ProjectFileExtensionRegistry projectFileExtensionRegistry, ImmutableDictionary? properties) { _solutionServices = solutionServices; _diagnosticReporter = diagnosticReporter; + _loggerFactory = loggerFactory; _pathResolver = new PathResolver(_diagnosticReporter); - _projectFileExtensionRegistry = projectFileExtensionRegistry ?? new ProjectFileExtensionRegistry(solutionServices, _diagnosticReporter); + _projectFileExtensionRegistry = projectFileExtensionRegistry; Properties = ImmutableDictionary.Create(StringComparer.OrdinalIgnoreCase); @@ -56,8 +58,19 @@ internal MSBuildProjectLoader( /// An optional dictionary of additional MSBuild properties and values to use when loading projects. /// These are the same properties that are passed to MSBuild via the /property:<n>=<v> command line argument. public MSBuildProjectLoader(Workspace workspace, ImmutableDictionary? properties = null) - : this(workspace.Services.SolutionServices, new DiagnosticReporter(workspace), projectFileExtensionRegistry: null, properties) { + _solutionServices = workspace.Services.SolutionServices; + _diagnosticReporter = new DiagnosticReporter(workspace); + _loggerFactory = DiagnosticReporterLoggerProvider.CreateLoggerFactoryForDiagnosticReporter(_diagnosticReporter); + _pathResolver = new PathResolver(_diagnosticReporter); + _projectFileExtensionRegistry = new ProjectFileExtensionRegistry(_solutionServices, _diagnosticReporter); + + Properties = ImmutableDictionary.Create(StringComparer.OrdinalIgnoreCase); + + if (properties != null) + { + Properties = Properties.AddRange(properties); + } } /// @@ -199,7 +212,7 @@ public async Task LoadSolutionInfoAsync( } } - var buildHostProcessManager = new BuildHostProcessManager(Properties); + var buildHostProcessManager = new BuildHostProcessManager(Properties, loggerFactory: _loggerFactory); await using var _ = buildHostProcessManager.ConfigureAwait(false); var worker = new Worker( @@ -261,7 +274,7 @@ public async Task> LoadProjectInfoAsync( onPathFailure: reportingMode, onLoaderFailure: reportingMode); - var buildHostProcessManager = new BuildHostProcessManager(Properties); + var buildHostProcessManager = new BuildHostProcessManager(Properties, loggerFactory: _loggerFactory); await using var _ = buildHostProcessManager.ConfigureAwait(false); var worker = new Worker( diff --git a/src/Workspaces/Core/MSBuild/MSBuild/MSBuildWorkspace.cs b/src/Workspaces/Core/MSBuild/MSBuild/MSBuildWorkspace.cs index b0b8d3da1139f..546d7a13e3348 100644 --- a/src/Workspaces/Core/MSBuild/MSBuild/MSBuildWorkspace.cs +++ b/src/Workspaces/Core/MSBuild/MSBuild/MSBuildWorkspace.cs @@ -31,6 +31,7 @@ public sealed class MSBuildWorkspace : Workspace private readonly NonReentrantLock _serializationLock = new(); private readonly MSBuildProjectLoader _loader; + private readonly Microsoft.Extensions.Logging.ILoggerFactory _loggerFactory; private readonly ProjectFileExtensionRegistry _projectFileExtensionRegistry; private readonly DiagnosticReporter _reporter; @@ -41,7 +42,8 @@ private MSBuildWorkspace( { _reporter = new DiagnosticReporter(this); _projectFileExtensionRegistry = new ProjectFileExtensionRegistry(Services.SolutionServices, _reporter); - _loader = new MSBuildProjectLoader(Services.SolutionServices, _reporter, _projectFileExtensionRegistry, properties); + _loggerFactory = DiagnosticReporterLoggerProvider.CreateLoggerFactoryForDiagnosticReporter(_reporter); + _loader = new MSBuildProjectLoader(Services.SolutionServices, _reporter, _loggerFactory, _projectFileExtensionRegistry, properties); } /// @@ -312,7 +314,7 @@ internal override bool TryApplyChanges(Solution newSolution, IProgress - + @@ -34,15 +34,9 @@ - true @@ -82,7 +76,7 @@ - + <_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\Core\MSBuild.BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj"> net472 BuildHost-net472 - <_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\Core\MSBuild.BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj"> - $(NetVSCode) - BuildHost-netcore - - - + + <_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\Core\MSBuild.BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj"> - $(NetRoslynToolset) + $(NetRoslynBuildHostNetCoreVersion) BuildHost-netcore diff --git a/src/Workspaces/Core/MSBuild/Rpc/RpcClient.cs b/src/Workspaces/Core/MSBuild/Rpc/RpcClient.cs index 7ba8ef734a0bd..98135bdb55e4e 100644 --- a/src/Workspaces/Core/MSBuild/Rpc/RpcClient.cs +++ b/src/Workspaces/Core/MSBuild/Rpc/RpcClient.cs @@ -139,14 +139,36 @@ public async Task InvokeAsync(int targetObject, string methodName, List new(this); + + internal readonly struct TestAccessor(RpcClient client) + { + public int GetOutstandingRequestCount() + => client._outstandingRequests.Count; + } } diff --git a/src/Workspaces/Core/Portable/Editing/ImportAdder.cs b/src/Workspaces/Core/Portable/Editing/ImportAdder.cs index 3659aeec125c1..34b0df71edd3c 100644 --- a/src/Workspaces/Core/Portable/Editing/ImportAdder.cs +++ b/src/Workspaces/Core/Portable/Editing/ImportAdder.cs @@ -39,7 +39,7 @@ public static async Task AddImportsAsync(Document document, OptionSet? /// Adds namespace imports / using directives for namespace references found in the document within the span specified. /// public static Task AddImportsAsync(Document document, TextSpan span, OptionSet? options = null, CancellationToken cancellationToken = default) - => AddImportsFromSyntaxesAsync(document, new[] { span }, options, cancellationToken); + => AddImportsFromSyntaxesAsync(document, [span], options, cancellationToken); /// /// Adds namespace imports / using directives for namespace references found in the document within the sub-trees annotated with the . diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs b/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs index f4f3d92dda54e..c31351276ae9f 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs @@ -209,7 +209,7 @@ public void InsertBefore(SyntaxNode node, IEnumerable newNodes) /// The node already existing in the tree that the new nodes will be placed before. This must be a node this is contained within a syntax list. /// The node to place before the existing node. This node must be of a compatible type to be placed in the same list containing the existing node. public void InsertBefore(SyntaxNode node, SyntaxNode newNode) - => InsertBefore(node, new[] { newNode }); + => InsertBefore(node, [newNode]); /// /// Insert the new nodes after the specified node already existing in the tree. @@ -231,7 +231,7 @@ public void InsertAfter(SyntaxNode node, IEnumerable newNodes) /// The node already existing in the tree that the new nodes will be placed after. This must be a node this is contained within a syntax list. /// The node to place after the existing node. This node must be of a compatible type to be placed in the same list containing the existing node. public void InsertAfter(SyntaxNode node, SyntaxNode newNode) - => this.InsertAfter(node, new[] { newNode }); + => this.InsertAfter(node, [newNode]); private void CheckNodeInOriginalTree(SyntaxNode node) { diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs b/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs index f1383a1855de2..0c06988fa4aff 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs @@ -50,22 +50,22 @@ public static void SetSetAccessorStatements(this SyntaxEditor editor, SyntaxNode => editor.ReplaceNode(declaration, (d, g) => g.WithSetAccessorStatements(d, statements)); public static void AddParameter(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode parameter) - => editor.ReplaceNode(declaration, (d, g) => g.AddParameters(d, new[] { parameter })); + => editor.ReplaceNode(declaration, (d, g) => g.AddParameters(d, [parameter])); public static void InsertParameter(this SyntaxEditor editor, SyntaxNode declaration, int index, SyntaxNode parameter) - => editor.ReplaceNode(declaration, (d, g) => g.InsertParameters(d, index, new[] { parameter })); + => editor.ReplaceNode(declaration, (d, g) => g.InsertParameters(d, index, [parameter])); public static void AddAttribute(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode attribute) - => editor.ReplaceNode(declaration, (d, g) => g.AddAttributes(d, new[] { attribute })); + => editor.ReplaceNode(declaration, (d, g) => g.AddAttributes(d, [attribute])); public static void AddReturnAttribute(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode attribute) - => editor.ReplaceNode(declaration, (d, g) => g.AddReturnAttributes(d, new[] { attribute })); + => editor.ReplaceNode(declaration, (d, g) => g.AddReturnAttributes(d, [attribute])); public static void AddAttributeArgument(this SyntaxEditor editor, SyntaxNode attributeDeclaration, SyntaxNode attributeArgument) - => editor.ReplaceNode(attributeDeclaration, (d, g) => g.AddAttributeArguments(d, new[] { attributeArgument })); + => editor.ReplaceNode(attributeDeclaration, (d, g) => g.AddAttributeArguments(d, [attributeArgument])); public static void AddMember(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode member) - => editor.ReplaceNode(declaration, (d, g) => g.AddMembers(d, new[] { member })); + => editor.ReplaceNode(declaration, (d, g) => g.AddMembers(d, [member])); public static void InsertMembers(this SyntaxEditor editor, SyntaxNode declaration, int index, IEnumerable members) => editor.ReplaceNode(declaration, (d, g) => g.InsertMembers(d, index, members)); diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs index 22cd75b420e24..9c89f4fa0965d 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs @@ -1664,7 +1664,7 @@ public abstract SyntaxNode IfStatement( /// The statements that are executed if the condition is true. /// A single statement that is executed if the condition is false. public SyntaxNode IfStatement(SyntaxNode condition, IEnumerable trueStatements, SyntaxNode falseStatement) - => IfStatement(condition, trueStatements, new[] { falseStatement }); + => IfStatement(condition, trueStatements, [falseStatement]); /// /// Creates a switch statement that branches to individual sections based on the value of the specified expression. @@ -1688,7 +1688,7 @@ public SyntaxNode SwitchStatement(SyntaxNode expression, params SyntaxNode[] sec /// Creates a single-case section a switch statement. /// public SyntaxNode SwitchSection(SyntaxNode caseExpression, IEnumerable statements) - => SwitchSection(new[] { caseExpression }, statements); + => SwitchSection([caseExpression], statements); /// /// Creates a default section for a switch statement. diff --git a/src/Workspaces/Core/Portable/FindSymbols/Shared/AbstractSyntaxIndex_Persistence.cs b/src/Workspaces/Core/Portable/FindSymbols/Shared/AbstractSyntaxIndex_Persistence.cs index 232f930859c53..e55367076c3e6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Shared/AbstractSyntaxIndex_Persistence.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Shared/AbstractSyntaxIndex_Persistence.cs @@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal partial class AbstractSyntaxIndex { private static readonly string s_persistenceName = typeof(TIndex).Name; - private static readonly Checksum s_serializationFormatChecksum = CodeAnalysis.Checksum.Create("38"); + private static readonly Checksum s_serializationFormatChecksum = CodeAnalysis.Checksum.Create("39"); /// /// Cache of ParseOptions to a checksum for the contained diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs index e092ef0d596ad..886c13d77a7ee 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Serialization.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Storage; using Roslyn.Utilities; @@ -191,7 +192,7 @@ static IEnumerable> GroupByName(ReadOnlyMemory sorted } private static SymbolTreeInfo? TryReadSymbolTreeInfo( - ObjectReader reader, Checksum checksum) + ObjectReader? reader, Checksum checksum) { if (reader == null) return null; @@ -203,7 +204,7 @@ static IEnumerable> GroupByName(ReadOnlyMemory sorted for (var i = 0; i < nodeCount; i++) { - var name = reader.ReadString(); + var name = reader.ReadRequiredString(); var groupCount = reader.ReadInt32(); for (var j = 0; j < groupCount; j++) { @@ -239,13 +240,13 @@ static IEnumerable> GroupByName(ReadOnlyMemory sorted for (var i = 0; i < keyCount; i++) { - var typeName = reader.ReadString(); + var typeName = reader.ReadRequiredString(); var valueCount = reader.ReadInt32(); for (var j = 0; j < valueCount; j++) { - var containerName = reader.ReadString(); - var name = reader.ReadString(); + var containerName = reader.ReadRequiredString(); + var name = reader.ReadRequiredString(); receiverTypeNameToExtensionMethodMap.Add(typeName, new ExtensionMethodInfo(containerName, name)); } diff --git a/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs b/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs index b1b0de3b81895..912386824133a 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Persistence.cs @@ -60,8 +60,8 @@ public override void WriteTo(ObjectWriter writer) for (var i = 0; i < globalAliasInfoCount; i++) { - var alias = reader.ReadString(); - var name = reader.ReadString(); + var alias = reader.ReadRequiredString(); + var name = reader.ReadRequiredString(); var arity = reader.ReadInt32(); globalAliasInfo.Add((alias, name, arity)); } diff --git a/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/DeclaredSymbolInfo.cs b/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/DeclaredSymbolInfo.cs index e2b3ab9c31a01..6bf19755c98ce 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/DeclaredSymbolInfo.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/DeclaredSymbolInfo.cs @@ -9,6 +9,7 @@ using System.Threading; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -185,26 +186,20 @@ internal void WriteTo(ObjectWriter writer) writer.WriteUInt32(_flags); writer.WriteInt32(Span.Start); writer.WriteInt32(Span.Length); - writer.WriteInt32(InheritanceNames.Length); - - foreach (var name in InheritanceNames) - writer.WriteString(name); + writer.WriteArray(InheritanceNames, static (w, n) => w.WriteString(n)); } internal static DeclaredSymbolInfo ReadFrom_ThrowsOnFailure(StringTable stringTable, ObjectReader reader) { - var name = reader.ReadString(); + var name = reader.ReadRequiredString(); var nameSuffix = reader.ReadString(); var containerDisplayName = reader.ReadString(); - var fullyQualifiedContainerName = reader.ReadString(); + var fullyQualifiedContainerName = reader.ReadRequiredString(); var flags = reader.ReadUInt32(); var spanStart = reader.ReadInt32(); var spanLength = reader.ReadInt32(); - var inheritanceNamesLength = reader.ReadInt32(); - using var _ = ArrayBuilder.GetInstance(inheritanceNamesLength, out var inheritanceNames); - for (var i = 0; i < inheritanceNamesLength; i++) - inheritanceNames.Add(reader.ReadString()); + var inheritanceNames = reader.ReadArray(static r => r.ReadRequiredString()); var span = new TextSpan(spanStart, spanLength); return Create( @@ -218,7 +213,7 @@ internal static DeclaredSymbolInfo ReadFrom_ThrowsOnFailure(StringTable stringTa GetKind(flags), GetAccessibility(flags), span, - inheritanceNames.ToImmutableAndClear(), + inheritanceNames, GetIsNestedType(flags), GetParameterCount(flags), GetTypeParameterCount(flags)); diff --git a/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.DeclarationInfo.cs b/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.DeclarationInfo.cs index d44f5ca36cee8..2da1374c4b776 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.DeclarationInfo.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.DeclarationInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindSymbols @@ -16,22 +17,14 @@ private readonly struct DeclarationInfo(ImmutableArray decla public ImmutableArray DeclaredSymbolInfos { get; } = declaredSymbolInfos; public void WriteTo(ObjectWriter writer) - { - writer.WriteInt32(DeclaredSymbolInfos.Length); - foreach (var declaredSymbolInfo in DeclaredSymbolInfos) - declaredSymbolInfo.WriteTo(writer); - } + => writer.WriteArray(DeclaredSymbolInfos, static (w, d) => d.WriteTo(w)); public static DeclarationInfo? TryReadFrom(StringTable stringTable, ObjectReader reader) { try { - var declaredSymbolCount = reader.ReadInt32(); - using var _ = ArrayBuilder.GetInstance(declaredSymbolCount, out var builder); - for (var i = 0; i < declaredSymbolCount; i++) - builder.Add(DeclaredSymbolInfo.ReadFrom_ThrowsOnFailure(stringTable, reader)); - - return new DeclarationInfo(builder.ToImmutableAndClear()); + var infos = reader.ReadArray(static (r, stringTable) => DeclaredSymbolInfo.ReadFrom_ThrowsOnFailure(stringTable, r), stringTable); + return new DeclarationInfo(infos); } catch (Exception) { diff --git a/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.ExtensionMethodInfo.cs b/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.ExtensionMethodInfo.cs index 3e10b8d41fdbb..760a312f34cc0 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.ExtensionMethodInfo.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/TopLevelSyntaxTree/TopLevelSyntaxTreeIndex.ExtensionMethodInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindSymbols @@ -50,10 +51,7 @@ public void WriteTo(ObjectWriter writer) foreach (var (name, indices) in ReceiverTypeNameToExtensionMethodMap) { writer.WriteString(name); - writer.WriteInt32(indices.Length); - - foreach (var declaredSymbolInfoIndex in indices) - writer.WriteInt32(declaredSymbolInfoIndex); + writer.WriteArray(indices, static (w, i) => w.WriteInt32(i)); } } @@ -65,16 +63,7 @@ public void WriteTo(ObjectWriter writer) var count = reader.ReadInt32(); for (var i = 0; i < count; ++i) - { - var typeName = reader.ReadString(); - var arrayLength = reader.ReadInt32(); - using var _ = ArrayBuilder.GetInstance(arrayLength, out var builder); - - for (var j = 0; j < arrayLength; ++j) - builder.Add(reader.ReadInt32()); - - receiverTypeNameToExtensionMethodMapBuilder[typeName] = builder.ToImmutableAndClear(); - } + receiverTypeNameToExtensionMethodMapBuilder[reader.ReadRequiredString()] = reader.ReadArray(static r => r.ReadInt32()); return new ExtensionMethodInfo(receiverTypeNameToExtensionMethodMapBuilder.ToImmutable()); } diff --git a/src/Workspaces/Core/Portable/Log/RoslynEventSource.cs b/src/Workspaces/Core/Portable/Log/RoslynEventSource.cs index c8123bd587ffd..7fb141784eddf 100644 --- a/src/Workspaces/Core/Portable/Log/RoslynEventSource.cs +++ b/src/Workspaces/Core/Portable/Log/RoslynEventSource.cs @@ -126,9 +126,9 @@ where attr is PerfGoalAttribute select ((PerfGoalAttribute)attr).InteractionClass).DefaultIfEmpty(InteractionClass.Undefined).First(); output.Append(value); - output.Append(" "); + output.Append(' '); output.Append(name); - output.Append(" "); + output.Append(' '); output.AppendLine(goal.ToString()); } diff --git a/src/Workspaces/Core/Portable/Remote/ISerializerService.cs b/src/Workspaces/Core/Portable/Remote/ISerializerService.cs index d4020c3f2d4b5..f6f74f5bae648 100644 --- a/src/Workspaces/Core/Portable/Remote/ISerializerService.cs +++ b/src/Workspaces/Core/Portable/Remote/ISerializerService.cs @@ -14,7 +14,7 @@ internal interface ISerializerService : IWorkspaceService void SerializeParseOptions(ParseOptions options, ObjectWriter writer); - T? Deserialize(WellKnownSynchronizationKind kind, ObjectReader reader, CancellationToken cancellationToken); + object Deserialize(WellKnownSynchronizationKind kind, ObjectReader reader, CancellationToken cancellationToken); Checksum CreateChecksum(object value, CancellationToken cancellationToken); Checksum CreateParseOptionsChecksum(ParseOptions value); diff --git a/src/Workspaces/Core/Portable/Serialization/AbstractOptionsSerializationService.cs b/src/Workspaces/Core/Portable/Serialization/AbstractOptionsSerializationService.cs index df19907bcaa5f..709109fe3c25e 100644 --- a/src/Workspaces/Core/Portable/Serialization/AbstractOptionsSerializationService.cs +++ b/src/Workspaces/Core/Portable/Serialization/AbstractOptionsSerializationService.cs @@ -36,7 +36,7 @@ protected static void WriteCompilationOptionsTo(CompilationOptions options, Obje writer.WriteString(options.CryptoKeyContainer); writer.WriteString(options.CryptoKeyFile); - writer.WriteValue(options.CryptoPublicKey.AsSpan()); + writer.WriteSpan(options.CryptoPublicKey.AsSpan()); writer.WriteBoolean(options.DelaySign.HasValue); if (options.DelaySign.HasValue) { @@ -73,57 +73,57 @@ protected static void WriteCompilationOptionsTo(CompilationOptions options, Obje // StrongNameProvider strongNameProvider } - protected static void ReadCompilationOptionsFrom( + protected static ( + OutputKind outputKind, + bool reportSuppressedDiagnostics, + string moduleName, + string mainTypeName, + string scriptClassName, + OptimizationLevel optimizationLevel, + bool checkOverflow, + string cryptoKeyContainer, + string cryptoKeyFile, + ImmutableArray cryptoPublicKey, + bool? delaySign, + Platform platform, + ReportDiagnostic generalDiagnosticOption, + int warningLevel, + IEnumerable> specificDiagnosticOptions, + bool concurrentBuild, + bool deterministic, + bool publicSign, + MetadataImportOptions metadataImportOptions, + XmlReferenceResolver xmlReferenceResolver, + SourceReferenceResolver sourceReferenceResolver, + MetadataReferenceResolver metadataReferenceResolver, + AssemblyIdentityComparer assemblyIdentityComparer, + StrongNameProvider strongNameProvider) ReadCompilationOptionsPieces( ObjectReader reader, - out OutputKind outputKind, - out bool reportSuppressedDiagnostics, - out string moduleName, - out string mainTypeName, - out string scriptClassName, - out OptimizationLevel optimizationLevel, - out bool checkOverflow, - out string cryptoKeyContainer, - out string cryptoKeyFile, - out ImmutableArray cryptoPublicKey, - out bool? delaySign, - out Platform platform, - out ReportDiagnostic generalDiagnosticOption, - out int warningLevel, - out IEnumerable> specificDiagnosticOptions, - out bool concurrentBuild, - out bool deterministic, - out bool publicSign, - out MetadataImportOptions metadataImportOptions, - out XmlReferenceResolver xmlReferenceResolver, - out SourceReferenceResolver sourceReferenceResolver, - out MetadataReferenceResolver metadataReferenceResolver, - out AssemblyIdentityComparer assemblyIdentityComparer, - out StrongNameProvider strongNameProvider, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - outputKind = (OutputKind)reader.ReadInt32(); - reportSuppressedDiagnostics = reader.ReadBoolean(); - moduleName = reader.ReadString(); - mainTypeName = reader.ReadString(); + var outputKind = (OutputKind)reader.ReadInt32(); + var reportSuppressedDiagnostics = reader.ReadBoolean(); + var moduleName = reader.ReadString(); + var mainTypeName = reader.ReadString(); - scriptClassName = reader.ReadString(); - optimizationLevel = (OptimizationLevel)reader.ReadInt32(); - checkOverflow = reader.ReadBoolean(); + var scriptClassName = reader.ReadString(); + var optimizationLevel = (OptimizationLevel)reader.ReadInt32(); + var checkOverflow = reader.ReadBoolean(); // REVIEW: is it okay this being not part of snapshot? - cryptoKeyContainer = reader.ReadString(); - cryptoKeyFile = reader.ReadString(); + var cryptoKeyContainer = reader.ReadString(); + var cryptoKeyFile = reader.ReadString(); - cryptoPublicKey = reader.ReadArray().ToImmutableArrayOrEmpty(); + var cryptoPublicKey = reader.ReadByteArray().ToImmutableArrayOrEmpty(); - delaySign = reader.ReadBoolean() ? reader.ReadBoolean() : null; + bool? delaySign = reader.ReadBoolean() ? reader.ReadBoolean() : null; - platform = (Platform)reader.ReadInt32(); - generalDiagnosticOption = (ReportDiagnostic)reader.ReadInt32(); + var platform = (Platform)reader.ReadInt32(); + var generalDiagnosticOption = (ReportDiagnostic)reader.ReadInt32(); - warningLevel = reader.ReadInt32(); + var warningLevel = reader.ReadInt32(); // REVIEW: I don't think there is a guarantee on ordering of elements in the immutable dictionary. // unfortunately, we need to sort them to make it deterministic @@ -145,21 +145,46 @@ protected static void ReadCompilationOptionsFrom( } } - specificDiagnosticOptions = specificDiagnosticOptionsList ?? SpecializedCollections.EmptyEnumerable>(); + var specificDiagnosticOptions = specificDiagnosticOptionsList ?? SpecializedCollections.EmptyEnumerable>(); - concurrentBuild = reader.ReadBoolean(); - deterministic = reader.ReadBoolean(); - publicSign = reader.ReadBoolean(); + var concurrentBuild = reader.ReadBoolean(); + var deterministic = reader.ReadBoolean(); + var publicSign = reader.ReadBoolean(); - metadataImportOptions = (MetadataImportOptions)reader.ReadByte(); + var metadataImportOptions = (MetadataImportOptions)reader.ReadByte(); // REVIEW: What should I do with these. are these service required when compilation is built ourselves, not through // compiler. - xmlReferenceResolver = XmlFileResolver.Default; - sourceReferenceResolver = SourceFileResolver.Default; - metadataReferenceResolver = null; - assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; - strongNameProvider = new DesktopStrongNameProvider(); + var xmlReferenceResolver = XmlFileResolver.Default; + var sourceReferenceResolver = SourceFileResolver.Default; + var assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; + var strongNameProvider = new DesktopStrongNameProvider(); + + return ( + outputKind, + reportSuppressedDiagnostics, + moduleName, + mainTypeName, + scriptClassName, + optimizationLevel, + checkOverflow, + cryptoKeyContainer, + cryptoKeyFile, + cryptoPublicKey, + delaySign, + platform, + generalDiagnosticOption, + warningLevel, + specificDiagnosticOptions, + concurrentBuild, + deterministic, + publicSign, + metadataImportOptions, + xmlReferenceResolver, + sourceReferenceResolver, + metadataReferenceResolver: null, + assemblyIdentityComparer, + strongNameProvider); } protected static void WriteParseOptionsTo(ParseOptions options, ObjectWriter writer) @@ -177,17 +202,14 @@ protected static void WriteParseOptionsTo(ParseOptions options, ObjectWriter wri } } - protected static void ReadParseOptionsFrom( + protected static (SourceCodeKind kind, DocumentationMode documentationMode, IEnumerable> features) ReadParseOptionsPieces( ObjectReader reader, - out SourceCodeKind kind, - out DocumentationMode documentationMode, - out IEnumerable> features, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - kind = (SourceCodeKind)reader.ReadInt32(); - documentationMode = (DocumentationMode)reader.ReadInt32(); + var kind = (SourceCodeKind)reader.ReadInt32(); + var documentationMode = (DocumentationMode)reader.ReadInt32(); // REVIEW: I don't think there is a guarantee on ordering of elements in the immutable dictionary. // unfortunately, we need to sort them to make it deterministic @@ -209,7 +231,8 @@ protected static void ReadParseOptionsFrom( } } - features = featuresList ?? SpecializedCollections.EmptyEnumerable>(); + var features = featuresList ?? SpecializedCollections.EmptyEnumerable>(); + return (kind, documentationMode, features); } } } diff --git a/src/Workspaces/Core/Portable/Serialization/ObjectReaderExtensions.cs b/src/Workspaces/Core/Portable/Serialization/ObjectReaderExtensions.cs deleted file mode 100644 index d83b1cd57dcdb..0000000000000 --- a/src/Workspaces/Core/Portable/Serialization/ObjectReaderExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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 disable - -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.Serialization -{ - // TODO: move to ObjectReader (see https://github.com/dotnet/roslyn/issues/45837) - internal static class ObjectReaderExtensions - { - public static T[] ReadArray(this ObjectReader reader) - => (T[])reader.ReadValue(); - } -} diff --git a/src/Workspaces/Core/Portable/Serialization/SerializableSourceText.cs b/src/Workspaces/Core/Portable/Serialization/SerializableSourceText.cs index 3fd97d161514e..fe0140097b001 100644 --- a/src/Workspaces/Core/Portable/Serialization/SerializableSourceText.cs +++ b/src/Workspaces/Core/Portable/Serialization/SerializableSourceText.cs @@ -150,14 +150,16 @@ public static SerializableSourceText Deserialize( cancellationToken.ThrowIfCancellationRequested(); var checksumAlgorithm = (SourceHashAlgorithm)reader.ReadInt32(); - var encoding = (Encoding)reader.ReadValue(); + var encoding = reader.ReadEncoding(); var kind = (SerializationKinds)reader.ReadInt32(); + Contract.ThrowIfFalse(kind is SerializationKinds.Bits or SerializationKinds.MemoryMapFile); + if (kind == SerializationKinds.MemoryMapFile) { var storage2 = (ITemporaryStorageService2)storageService; - var name = reader.ReadString(); + var name = reader.ReadRequiredString(); var offset = reader.ReadInt64(); var size = reader.ReadInt64(); @@ -171,9 +173,10 @@ public static SerializableSourceText Deserialize( return new SerializableSourceText(storage.ReadText(cancellationToken)); } } - - Contract.ThrowIfFalse(kind == SerializationKinds.Bits); - return new SerializableSourceText(SourceTextExtensions.ReadFrom(textService, reader, encoding, checksumAlgorithm, cancellationToken)); + else + { + return new SerializableSourceText(SourceTextExtensions.ReadFrom(textService, reader, encoding, checksumAlgorithm, cancellationToken)); + } } } } diff --git a/src/Workspaces/Core/Portable/Serialization/SerializerService.cs b/src/Workspaces/Core/Portable/Serialization/SerializerService.cs index a6de0ba7cc90f..33ce36e947f2a 100644 --- a/src/Workspaces/Core/Portable/Serialization/SerializerService.cs +++ b/src/Workspaces/Core/Portable/Serialization/SerializerService.cs @@ -180,55 +180,32 @@ public void Serialize(object value, ObjectWriter writer, SolutionReplicationCont } } - public T Deserialize(WellKnownSynchronizationKind kind, ObjectReader reader, CancellationToken cancellationToken) + public object Deserialize(WellKnownSynchronizationKind kind, ObjectReader reader, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Serializer_Deserialize, s_logKind, kind, cancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); - switch (kind) + return kind switch { - case WellKnownSynchronizationKind.SolutionCompilationState: - return (T)(object)SolutionCompilationStateChecksums.Deserialize(reader); - - case WellKnownSynchronizationKind.SolutionState: - return (T)(object)SolutionStateChecksums.Deserialize(reader); - - case WellKnownSynchronizationKind.ProjectState: - return (T)(object)ProjectStateChecksums.Deserialize(reader); - - case WellKnownSynchronizationKind.DocumentState: - return (T)(object)DocumentStateChecksums.Deserialize(reader); - - case WellKnownSynchronizationKind.ChecksumCollection: - return (T)(object)ChecksumCollection.ReadFrom(reader); - - case WellKnownSynchronizationKind.SolutionAttributes: - return (T)(object)SolutionInfo.SolutionAttributes.ReadFrom(reader); - case WellKnownSynchronizationKind.ProjectAttributes: - return (T)(object)ProjectInfo.ProjectAttributes.ReadFrom(reader); - case WellKnownSynchronizationKind.DocumentAttributes: - return (T)(object)DocumentInfo.DocumentAttributes.ReadFrom(reader); - case WellKnownSynchronizationKind.SourceGeneratedDocumentIdentity: - return (T)(object)SourceGeneratedDocumentIdentity.ReadFrom(reader); - case WellKnownSynchronizationKind.CompilationOptions: - return (T)(object)DeserializeCompilationOptions(reader, cancellationToken); - case WellKnownSynchronizationKind.ParseOptions: - return (T)(object)DeserializeParseOptions(reader, cancellationToken); - case WellKnownSynchronizationKind.ProjectReference: - return (T)(object)DeserializeProjectReference(reader, cancellationToken); - case WellKnownSynchronizationKind.MetadataReference: - return (T)(object)DeserializeMetadataReference(reader, cancellationToken); - case WellKnownSynchronizationKind.AnalyzerReference: - return (T)(object)DeserializeAnalyzerReference(reader, cancellationToken); - case WellKnownSynchronizationKind.SerializableSourceText: - return (T)(object)SerializableSourceText.Deserialize(reader, _storageService, _textService, cancellationToken); - case WellKnownSynchronizationKind.SourceText: - return (T)(object)DeserializeSourceText(reader, cancellationToken); - - default: - throw ExceptionUtilities.UnexpectedValue(kind); - } + WellKnownSynchronizationKind.SolutionCompilationState => SolutionCompilationStateChecksums.Deserialize(reader), + WellKnownSynchronizationKind.SolutionState => SolutionStateChecksums.Deserialize(reader), + WellKnownSynchronizationKind.ProjectState => ProjectStateChecksums.Deserialize(reader), + WellKnownSynchronizationKind.DocumentState => DocumentStateChecksums.Deserialize(reader), + WellKnownSynchronizationKind.ChecksumCollection => ChecksumCollection.ReadFrom(reader), + WellKnownSynchronizationKind.SolutionAttributes => SolutionInfo.SolutionAttributes.ReadFrom(reader), + WellKnownSynchronizationKind.ProjectAttributes => ProjectInfo.ProjectAttributes.ReadFrom(reader), + WellKnownSynchronizationKind.DocumentAttributes => DocumentInfo.DocumentAttributes.ReadFrom(reader), + WellKnownSynchronizationKind.SourceGeneratedDocumentIdentity => SourceGeneratedDocumentIdentity.ReadFrom(reader), + WellKnownSynchronizationKind.CompilationOptions => DeserializeCompilationOptions(reader, cancellationToken), + WellKnownSynchronizationKind.ParseOptions => DeserializeParseOptions(reader, cancellationToken), + WellKnownSynchronizationKind.ProjectReference => DeserializeProjectReference(reader, cancellationToken), + WellKnownSynchronizationKind.MetadataReference => DeserializeMetadataReference(reader, cancellationToken), + WellKnownSynchronizationKind.AnalyzerReference => DeserializeAnalyzerReference(reader, cancellationToken), + WellKnownSynchronizationKind.SerializableSourceText => SerializableSourceText.Deserialize(reader, _storageService, _textService, cancellationToken), + WellKnownSynchronizationKind.SourceText => DeserializeSourceText(reader, cancellationToken), + _ => throw ExceptionUtilities.UnexpectedValue(kind), + }; } } @@ -243,6 +220,5 @@ public Checksum CreateParseOptionsChecksum(ParseOptions value) internal enum SerializationKinds { Bits, - FilePath, MemoryMapFile } diff --git a/src/Workspaces/Core/Portable/Serialization/SerializerService_Asset.cs b/src/Workspaces/Core/Portable/Serialization/SerializerService_Asset.cs index 1e2386b6f9c98..9a59c289d4d95 100644 --- a/src/Workspaces/Core/Portable/Serialization/SerializerService_Asset.cs +++ b/src/Workspaces/Core/Portable/Serialization/SerializerService_Asset.cs @@ -45,7 +45,7 @@ private CompilationOptions DeserializeCompilationOptions(ObjectReader reader, Ca { cancellationToken.ThrowIfCancellationRequested(); - var language = reader.ReadString(); + var language = reader.ReadRequiredString(); var service = GetOptionsSerializationService(language); return service.ReadCompilationOptionsFrom(reader, cancellationToken); @@ -66,7 +66,7 @@ private ParseOptions DeserializeParseOptions(ObjectReader reader, CancellationTo { cancellationToken.ThrowIfCancellationRequested(); - var language = reader.ReadString(); + var language = reader.ReadRequiredString(); var service = GetOptionsSerializationService(language); return service.ReadParseOptionsFrom(reader, cancellationToken); @@ -77,7 +77,7 @@ private static void SerializeProjectReference(ProjectReference reference, Object cancellationToken.ThrowIfCancellationRequested(); reference.ProjectId.WriteTo(writer); - writer.WriteValue(reference.Aliases.ToArray()); + writer.WriteArray(reference.Aliases, static (w, a) => w.WriteString(a)); writer.WriteBoolean(reference.EmbedInteropTypes); } @@ -86,7 +86,7 @@ private static ProjectReference DeserializeProjectReference(ObjectReader reader, cancellationToken.ThrowIfCancellationRequested(); var projectId = ProjectId.ReadFrom(reader); - var aliases = reader.ReadArray(); + var aliases = reader.ReadArray(static r => r.ReadString()); var embedInteropTypes = reader.ReadBoolean(); return new ProjectReference(projectId, aliases.ToImmutableArrayOrEmpty(), embedInteropTypes); diff --git a/src/Workspaces/Core/Portable/Serialization/SerializerService_Reference.cs b/src/Workspaces/Core/Portable/Serialization/SerializerService_Reference.cs index bc4ffd25e83ee..41691195c7440 100644 --- a/src/Workspaces/Core/Portable/Serialization/SerializerService_Reference.cs +++ b/src/Workspaces/Core/Portable/Serialization/SerializerService_Reference.cs @@ -14,6 +14,7 @@ using System.Threading; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Serialization @@ -115,7 +116,7 @@ public virtual AnalyzerReference ReadAnalyzerReferenceFrom(ObjectReader reader, var type = reader.ReadString(); if (type == nameof(AnalyzerFileReference)) { - var fullPath = reader.ReadString(); + var fullPath = reader.ReadRequiredString(); var shadowCopy = reader.ReadBoolean(); return new AnalyzerFileReference(fullPath, _analyzerLoaderProvider.GetLoader(new AnalyzerAssemblyLoaderOptions(shadowCopy))); } @@ -228,37 +229,34 @@ private static void WritePortableExecutableReferenceTo( private PortableExecutableReference ReadPortableExecutableReferenceFrom(ObjectReader reader, CancellationToken cancellationToken) { var kind = (SerializationKinds)reader.ReadInt32(); - if (kind is SerializationKinds.Bits or SerializationKinds.MemoryMapFile) - { - var properties = ReadMetadataReferencePropertiesFrom(reader, cancellationToken); - - var filePath = reader.ReadString(); + Contract.ThrowIfFalse(kind is SerializationKinds.Bits or SerializationKinds.MemoryMapFile); - var tuple = TryReadMetadataFrom(reader, kind, cancellationToken); - if (tuple == null) - { - // TODO: deal with xml document provider properly - // should we shadow copy xml doc comment? + var properties = ReadMetadataReferencePropertiesFrom(reader, cancellationToken); - // image doesn't exist - return new MissingMetadataReference(properties, filePath, XmlDocumentationProvider.Default); - } + var filePath = reader.ReadString(); - // for now, we will use IDocumentationProviderService to get DocumentationProvider for metadata - // references. if the service is not available, then use Default (NoOp) provider. - // since xml doc comment is not part of solution snapshot, (like xml reference resolver or strong name - // provider) this provider can also potentially provide content that is different than one in the host. - // an alternative approach of this is synching content of xml doc comment to remote host as well - // so that we can put xml doc comment as part of snapshot. but until we believe that is necessary, - // it will go with simpler approach - var documentProvider = filePath != null && _documentationService != null ? - _documentationService.GetDocumentationProvider(filePath) : XmlDocumentationProvider.Default; + var tuple = TryReadMetadataFrom(reader, kind, cancellationToken); + if (tuple == null) + { + // TODO: deal with xml document provider properly + // should we shadow copy xml doc comment? - return new SerializedMetadataReference( - properties, filePath, tuple.Value.metadata, tuple.Value.storages, documentProvider); + // image doesn't exist + return new MissingMetadataReference(properties, filePath, XmlDocumentationProvider.Default); } - throw ExceptionUtilities.UnexpectedValue(kind); + // for now, we will use IDocumentationProviderService to get DocumentationProvider for metadata + // references. if the service is not available, then use Default (NoOp) provider. + // since xml doc comment is not part of solution snapshot, (like xml reference resolver or strong name + // provider) this provider can also potentially provide content that is different than one in the host. + // an alternative approach of this is synching content of xml doc comment to remote host as well + // so that we can put xml doc comment as part of snapshot. but until we believe that is necessary, + // it will go with simpler approach + var documentProvider = filePath != null && _documentationService != null ? + _documentationService.GetDocumentationProvider(filePath) : XmlDocumentationProvider.Default; + + return new SerializedMetadataReference( + properties, filePath, tuple.Value.metadata, tuple.Value.storages, documentProvider); } private static void WriteTo(MetadataReferenceProperties properties, ObjectWriter writer, CancellationToken cancellationToken) @@ -266,7 +264,7 @@ private static void WriteTo(MetadataReferenceProperties properties, ObjectWriter cancellationToken.ThrowIfCancellationRequested(); writer.WriteInt32((int)properties.Kind); - writer.WriteValue(properties.Aliases.ToArray()); + writer.WriteArray(properties.Aliases, static (w, a) => w.WriteString(a)); writer.WriteBoolean(properties.EmbedInteropTypes); } @@ -275,7 +273,7 @@ private static MetadataReferenceProperties ReadMetadataReferencePropertiesFrom(O cancellationToken.ThrowIfCancellationRequested(); var kind = (MetadataImageKind)reader.ReadInt32(); - var aliases = reader.ReadArray().ToImmutableArrayOrEmpty(); + var aliases = reader.ReadArray(static r => r.ReadRequiredString()); var embedInteropTypes = reader.ReadBoolean(); return new MetadataReferenceProperties(kind, aliases, embedInteropTypes); @@ -422,7 +420,7 @@ private static bool TryWritePortableExecutableReferenceBackedByTemporaryStorageT { cancellationToken.ThrowIfCancellationRequested(); - GetTemporaryStorage(reader, kind, out var storage, out var length, cancellationToken); + var (storage, length) = GetTemporaryStorage(reader, kind, cancellationToken); var storageStream = storage.ReadStream(cancellationToken); Contract.ThrowIfFalse(length == storageStream.Length); @@ -441,7 +439,7 @@ private static ModuleMetadata ReadModuleMetadataFrom(ObjectReader reader, Serial { Contract.ThrowIfFalse(SerializationKinds.Bits == kind); - var array = reader.ReadArray(); + var array = reader.ReadByteArray(); var pinnedObject = new PinnedObject(array); var metadata = ModuleMetadata.CreateFromMetadata(pinnedObject.GetPointer(), array.Length); @@ -453,39 +451,38 @@ private static ModuleMetadata ReadModuleMetadataFrom(ObjectReader reader, Serial return metadata; } - private void GetTemporaryStorage( - ObjectReader reader, SerializationKinds kind, out ITemporaryStreamStorageInternal storage, out long length, CancellationToken cancellationToken) + private (ITemporaryStreamStorageInternal storage, long length) GetTemporaryStorage( + ObjectReader reader, SerializationKinds kind, CancellationToken cancellationToken) { + Contract.ThrowIfFalse(kind is SerializationKinds.Bits or SerializationKinds.MemoryMapFile); + if (kind == SerializationKinds.Bits) { - storage = _storageService.CreateTemporaryStreamStorage(); + var storage = _storageService.CreateTemporaryStreamStorage(); using var stream = SerializableBytes.CreateWritableStream(); CopyByteArrayToStream(reader, stream, cancellationToken); - length = stream.Length; + var length = stream.Length; stream.Position = 0; storage.WriteStream(stream, cancellationToken); - return; + return (storage, length); } - - if (kind == SerializationKinds.MemoryMapFile) + else { var service2 = (ITemporaryStorageService2)_storageService; - var name = reader.ReadString(); + var name = reader.ReadRequiredString(); var offset = reader.ReadInt64(); var size = reader.ReadInt64(); - storage = service2.AttachTemporaryStreamStorage(name, offset, size); - length = size; + var storage = service2.AttachTemporaryStreamStorage(name, offset, size); + var length = size; - return; + return (storage, length); } - - throw ExceptionUtilities.UnexpectedValue(kind); } private static void GetMetadata(Stream stream, long length, out ModuleMetadata metadata, out object? lifeTimeObject) @@ -525,7 +522,7 @@ private static void CopyByteArrayToStream(ObjectReader reader, Stream stream, Ca cancellationToken.ThrowIfCancellationRequested(); // TODO: make reader be able to read byte[] chunk - var content = reader.ReadArray(); + var content = reader.ReadByteArray(); stream.Write(content, 0, content.Length); } @@ -540,7 +537,7 @@ private static unsafe void WriteTo(MetadataReader reader, ObjectWriter writer, C { cancellationToken.ThrowIfCancellationRequested(); - writer.WriteValue(new ReadOnlySpan(reader.MetadataPointer, reader.MetadataLength)); + writer.WriteSpan(new ReadOnlySpan(reader.MetadataPointer, reader.MetadataLength)); } private static void WriteUnresolvedAnalyzerReferenceTo(AnalyzerReference reference, ObjectWriter writer) diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/INamedTypeSymbolExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/INamedTypeSymbolExtensions.cs index 0bf0f221cbfef..115faf1df63d5 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/INamedTypeSymbolExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/INamedTypeSymbolExtensions.cs @@ -14,7 +14,7 @@ public static INamespaceOrTypeSymbol GenerateRootNamespaceOrType(this INamedType for (var i = containers.Length - 1; i >= 0; i--) { - currentSymbol = CodeGenerationSymbolFactory.CreateNamespaceSymbol(containers[i], members: new[] { currentSymbol }); + currentSymbol = CodeGenerationSymbolFactory.CreateNamespaceSymbol(containers[i], members: [currentSymbol]); } return currentSymbol; diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs index 8db046cfd4db1..47d9178365398 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs @@ -17,6 +17,16 @@ namespace Microsoft.CodeAnalysis.Shared.Extensions; internal static partial class SourceTextExtensions { + // char pooled memory : 8K * 256 = 2MB + private const int CharArrayLength = 4 * 1024; + + /// + /// Note: there is a strong invariant that you only get arrays back from this that are exactly long. Putting arrays back into this of the wrong length will result in broken + /// behavior. Do not expose this pool outside of this class. + /// + private static readonly ObjectPool s_charArrayPool = new(() => new char[CharArrayLength], 256); + public static void GetLineAndOffset(this SourceText text, int position, out int lineNumber, out int offset) { var line = text.Lines.GetLineFromPosition(position); @@ -182,46 +192,39 @@ public static void WriteTo(this SourceText sourceText, ObjectWriter writer, Canc private static void WriteChunksTo(SourceText sourceText, ObjectWriter writer, int length, CancellationToken cancellationToken) { // chunk size - var buffer = SharedPools.CharArray.Allocate(); - writer.WriteInt32(buffer.Length); + using var pooledObject = s_charArrayPool.GetPooledObject(); + var buffer = pooledObject.Object; + Contract.ThrowIfTrue(buffer.Length != CharArrayLength); + + // We write out the chunk size for sanity purposes. + writer.WriteInt32(CharArrayLength); // number of chunks var numberOfChunks = 1 + (length / buffer.Length); writer.WriteInt32(numberOfChunks); // write whole chunks - try + var offset = 0; + for (var i = 0; i < numberOfChunks; i++) { - var offset = 0; - for (var i = 0; i < numberOfChunks; i++) - { - cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); - var count = Math.Min(buffer.Length, length - offset); - if ((i < numberOfChunks - 1) || (count == buffer.Length)) - { - // chunks before last chunk or last chunk match buffer size - sourceText.CopyTo(offset, buffer, 0, buffer.Length); - writer.WriteValue(buffer); - } - else if (i == numberOfChunks - 1) - { - // last chunk which size is not buffer size - var tempArray = new char[count]; + var count = Math.Min(buffer.Length, length - offset); + sourceText.CopyTo(offset, buffer, 0, count); - sourceText.CopyTo(offset, tempArray, 0, tempArray.Length); - writer.WriteValue(tempArray); - } - - offset += count; - } + // In the case where the array is entirely full, we can pass that as is to the ObjectWriter. It already + // supports sending the array all the way through to the underlying stream without allocations. In the case + // where it's partially full, we pass in a span to the section that is filled. This will fast path on + // netcore, though will incur a copy to pooled memory on netfx. + if (count == buffer.Length) + writer.WriteCharArray(buffer); + else + writer.WriteSpan(buffer.AsSpan()[..count]); - Contract.ThrowIfFalse(offset == length); - } - finally - { - SharedPools.CharArray.Free(buffer); + offset += count; } + + Contract.ThrowIfFalse(offset == length); } public static SourceText ReadFrom(ITextFactoryService textService, ObjectReader reader, Encoding? encoding, SourceHashAlgorithm checksumAlgorithm, CancellationToken cancellationToken) @@ -231,7 +234,7 @@ public static SourceText ReadFrom(ITextFactoryService textService, ObjectReader return textService.CreateText(textReader, encoding, checksumAlgorithm, cancellationToken); } - private class ObjectReaderTextReader : TextReaderWithLength + private sealed class ObjectReaderTextReader : TextReaderWithLength { private readonly ImmutableArray _chunks; private readonly int _chunkSize; @@ -245,33 +248,38 @@ public static TextReader Create(ObjectReader reader) if (length < SourceTextLengthThreshold) { // small size, read as string - return new StringReader(reader.ReadString()); + return new StringReader(reader.ReadRequiredString()); } - // read as chunks - using var _ = ArrayBuilder.GetInstance(out var builder); - var chunkSize = reader.ReadInt32(); + Contract.ThrowIfTrue(chunkSize != CharArrayLength); var numberOfChunks = reader.ReadInt32(); + // read as chunks + using var _ = ArrayBuilder.GetInstance(numberOfChunks, out var chunks); + var offset = 0; for (var i = 0; i < numberOfChunks; i++) { - var (currentChunk, currentChunkLength) = reader.ReadCharArray(static length => - { - if (length <= SharedPools.CharBufferSize) - return SharedPools.CharArray.Allocate(); + // Shared pool array will be freed in the Dispose method below. + var (currentChunk, currentChunkLength) = reader.ReadCharArray( + static length => + { + Contract.ThrowIfTrue(length > CharArrayLength); + return s_charArrayPool.Allocate(); + }); - return new char[length]; - }); + Contract.ThrowIfTrue(currentChunk.Length != CharArrayLength); - builder.Add(currentChunk); + // All but the last chunk must be completely filled. + Contract.ThrowIfTrue(i < numberOfChunks - 1 && currentChunkLength != CharArrayLength); + chunks.Add(currentChunk); offset += currentChunkLength; } Contract.ThrowIfFalse(offset == length); - return new ObjectReaderTextReader(builder.ToImmutable(), chunkSize, length); + return new ObjectReaderTextReader(chunks.ToImmutableAndClear(), chunkSize, length); } private ObjectReaderTextReader(ImmutableArray chunks, int chunkSize, int length) @@ -280,6 +288,8 @@ private ObjectReaderTextReader(ImmutableArray chunks, int chunkSize, int _chunks = chunks; _chunkSize = chunkSize; _disposed = false; + Contract.ThrowIfTrue(chunkSize != CharArrayLength); + Contract.ThrowIfTrue(chunks.Any(static (c, s) => c.Length != s, chunkSize)); } protected override void Dispose(bool disposing) @@ -287,11 +297,10 @@ protected override void Dispose(bool disposing) if (!_disposed) { _disposed = true; + + // Constructor already validated that all chunks are the right size to go back into the pool. foreach (var chunk in _chunks) - { - if (chunk.Length <= SharedPools.CharBufferSize) - SharedPools.CharArray.Free(chunk); - } + s_charArrayPool.Free(chunk); } base.Dispose(disposing); diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SyntaxGeneratorExtensions_CreateEqualsMethod.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SyntaxGeneratorExtensions_CreateEqualsMethod.cs index 3112599e10930..e9acaafd6cb28 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/SyntaxGeneratorExtensions_CreateEqualsMethod.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SyntaxGeneratorExtensions_CreateEqualsMethod.cs @@ -153,7 +153,7 @@ private static ImmutableArray CreateEqualsMethodStatements( factory.IsTypeExpression( objNameExpression, containingType)), - new[] { factory.ReturnStatement(factory.FalseLiteralExpression()) }); + [factory.ReturnStatement(factory.FalseLiteralExpression())]); // Next, we cast the argument to our type: // diff --git a/src/Workspaces/Core/Portable/Storage/CloudCache/ICloudCacheStorageServiceProvider.cs b/src/Workspaces/Core/Portable/Storage/CloudCache/ICloudCacheStorageServiceProvider.cs deleted file mode 100644 index 5ea4652c701d7..0000000000000 --- a/src/Workspaces/Core/Portable/Storage/CloudCache/ICloudCacheStorageServiceProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -using Microsoft.CodeAnalysis.Host; - -namespace Microsoft.CodeAnalysis.Storage.CloudCache -{ - internal interface ICloudCacheStorageService : IChecksummedPersistentStorageService, IWorkspaceService - { - } -} diff --git a/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs b/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs index 6272d6d690564..08cd17a21f9e5 100644 --- a/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs +++ b/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Storage.CloudCache; #if !DOTNET_BUILD_FROM_SOURCE using Microsoft.CodeAnalysis.SQLite.v2; @@ -26,9 +25,6 @@ public static IChecksummedPersistentStorageService GetPersistentStorageService(t => services.GetService() ?? NoOpPersistentStorageService.GetOrThrow(configuration), #endif - StorageDatabase.CloudCache - => services.GetService() ?? - NoOpPersistentStorageService.GetOrThrow(configuration), _ => NoOpPersistentStorageService.GetOrThrow(configuration), }; } diff --git a/src/Workspaces/Core/Portable/Storage/StorageDatabase.cs b/src/Workspaces/Core/Portable/Storage/StorageDatabase.cs index 150f02a3469e8..4587658fe8c46 100644 --- a/src/Workspaces/Core/Portable/Storage/StorageDatabase.cs +++ b/src/Workspaces/Core/Portable/Storage/StorageDatabase.cs @@ -8,6 +8,5 @@ internal enum StorageDatabase { None = 0, SQLite = 1, - CloudCache = 2, } } diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs index ee336c470b3e8..92238004ccefd 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs @@ -113,10 +113,12 @@ public async Task CreateAndAddToWorkspaceAsync(string proj compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions); - await ApplyChangeToWorkspaceAsync(async w => + await ApplyChangeToWorkspaceAsync(w => { - await w.SetCurrentSolutionAsync( - useAsync: true, + // We call the synchronous SetCurrentSolution which is fine here since we've already acquired our outer lock so this will + // never block. But once we remove the ProjectSystemProjectFactory lock in favor of everybody calling the newer overloads of + // SetCurrentSolution, this should become async again. + w.SetCurrentSolution( oldSolution => { // If we don't have any projects and this is our first project being added, then we'll create a @@ -127,7 +129,7 @@ await w.SetCurrentSolutionAsync( SolutionId.CreateNewId(SolutionPath), VersionStamp.Create(), SolutionPath, - projects: new[] { projectInfo }, + projects: [projectInfo], analyzerReferences: w.CurrentSolution.AnalyzerReferences).WithTelemetryId(SolutionTelemetryId); var newSolution = w.CreateSolution(solutionInfo); @@ -148,8 +150,7 @@ await w.SetCurrentSolutionAsync( : (WorkspaceChangeKind.ProjectAdded, projectId, documentId: null); }, onBeforeUpdate: null, - onAfterUpdate: null, - CancellationToken.None).ConfigureAwait(false); + onAfterUpdate: null); }).ConfigureAwait(false); return project; @@ -195,11 +196,11 @@ public void ApplyChangeToWorkspace(Action action) /// /// Applies a single operation to the workspace. should be a call to one of the protected Workspace.On* methods. /// - public async ValueTask ApplyChangeToWorkspaceAsync(Func action, CancellationToken cancellationToken = default) + public async ValueTask ApplyChangeToWorkspaceAsync(Action action, CancellationToken cancellationToken = default) { using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { - await action(Workspace).ConfigureAwait(false); + action(Workspace); } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ChecksumCollection.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ChecksumCollection.cs index 764df62b1c302..80e04bb9ed8e8 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ChecksumCollection.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ChecksumCollection.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Serialization; @@ -19,12 +20,21 @@ namespace Microsoft.CodeAnalysis.Serialization; /// internal readonly struct ChecksumCollection(ImmutableArray children) : IReadOnlyCollection { + /// + /// Aggregate checksum produced from all the constituent checksums in . + /// public Checksum Checksum { get; } = Checksum.Create(children); public int Count => children.Length; public Checksum this[int index] => children[index]; public ImmutableArray Children => children; + /// + /// Enumerates the child checksums (found in ) that make up this collection. This is + /// equivalent to directly enumerating the property. Importantly, is + /// not part of this enumeration. is the checksum produced by all those child + /// checksums. + /// public ImmutableArray.Enumerator GetEnumerator() => children.GetEnumerator(); @@ -97,19 +107,8 @@ internal static void Find( } public void WriteTo(ObjectWriter writer) - { - writer.WriteInt32(this.Count); - foreach (var obj in this.Children) - obj.WriteTo(writer); - } + => writer.WriteArray(this.Children, static (w, c) => c.WriteTo(w)); public static ChecksumCollection ReadFrom(ObjectReader reader) - { - var count = reader.ReadInt32(); - using var _ = ArrayBuilder.GetInstance(count, out var result); - for (var i = 0; i < count; i++) - result.Add(Checksum.ReadFrom(reader)); - - return new(result.ToImmutableAndClear()); - } + => new(reader.ReadArray(Checksum.ReadFrom)); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs index f8cd33f2876d0..4e3d863a09038 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs @@ -448,7 +448,7 @@ internal virtual Document WithFrozenPartialSemantics(CancellationToken cancellat this.Project.SupportsCompilation) { var newSolution = this.Project.Solution.WithFrozenPartialCompilationIncludingSpecificDocument(this.Id, cancellationToken); - return newSolution.GetDocument(this.Id)!; + return newSolution.GetRequiredDocument(this.Id); } else { diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs index c255884a942a2..d8a7603f1fc60 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis @@ -233,7 +234,7 @@ public void WriteTo(ObjectWriter writer) Id.WriteTo(writer); writer.WriteString(Name); - writer.WriteValue(Folders.ToArray()); + writer.WriteArray(Folders.ToImmutableArrayOrEmpty(), static (w, f) => w.WriteString(f)); writer.WriteByte(checked((byte)SourceCodeKind)); writer.WriteString(FilePath); writer.WriteBoolean(IsGenerated); @@ -244,8 +245,8 @@ public static DocumentAttributes ReadFrom(ObjectReader reader) { var documentId = DocumentId.ReadFrom(reader); - var name = reader.ReadString(); - var folders = (string[])reader.ReadValue(); + var name = reader.ReadRequiredString(); + var folders = reader.ReadArray(static r => r.ReadRequiredString()); var sourceCodeKind = (SourceCodeKind)reader.ReadByte(); var filePath = reader.ReadString(); var isGenerated = reader.ReadBoolean(); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_LinkedFileReuse.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_LinkedFileReuse.cs index 5a8cb24939fd6..14b193623eb53 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_LinkedFileReuse.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState_LinkedFileReuse.cs @@ -19,7 +19,10 @@ internal partial class DocumentState /// name="siblingTextSource"/> if possible, or which will incrementally parse the current tree to bring it up to /// date with otherwise. /// - public DocumentState UpdateTextAndTreeContents(ITextAndVersionSource siblingTextSource, AsyncLazy? siblingTreeSource) + public DocumentState UpdateTextAndTreeContents( + ITextAndVersionSource siblingTextSource, + AsyncLazy? siblingTreeSource, + bool forceEvenIfTreesWouldDiffer) { if (!SupportsSyntaxTree) { @@ -53,7 +56,7 @@ public DocumentState UpdateTextAndTreeContents(ITextAndVersionSource siblingText var treeSource = this.TreeSource; var newTreeSource = GetReuseTreeSource( - filePath, languageServices, loadTextOptions, parseOptions, treeSource, siblingTextSource, siblingTreeSource); + filePath, languageServices, loadTextOptions, parseOptions, treeSource, siblingTextSource, siblingTreeSource, forceEvenIfTreesWouldDiffer); return new DocumentState( languageServices, @@ -71,11 +74,12 @@ static AsyncLazy GetReuseTreeSource( ParseOptions parseOptions, AsyncLazy treeSource, ITextAndVersionSource siblingTextSource, - AsyncLazy siblingTreeSource) + AsyncLazy siblingTreeSource, + bool forceEvenIfTreesWouldDiffer) { return new AsyncLazy( - cancellationToken => TryReuseSiblingTreeAsync(filePath, languageServices, loadTextOptions, parseOptions, treeSource, siblingTextSource, siblingTreeSource, cancellationToken), - cancellationToken => TryReuseSiblingTree(filePath, languageServices, loadTextOptions, parseOptions, treeSource, siblingTextSource, siblingTreeSource, cancellationToken)); + cancellationToken => TryReuseSiblingTreeAsync(filePath, languageServices, loadTextOptions, parseOptions, treeSource, siblingTextSource, siblingTreeSource, forceEvenIfTreesWouldDiffer, cancellationToken), + cancellationToken => TryReuseSiblingTree(filePath, languageServices, loadTextOptions, parseOptions, treeSource, siblingTextSource, siblingTreeSource, forceEvenIfTreesWouldDiffer, cancellationToken)); } static bool TryReuseSiblingRoot( @@ -85,12 +89,13 @@ static bool TryReuseSiblingRoot( ParseOptions parseOptions, SyntaxNode siblingRoot, VersionStamp siblingVersion, + bool forceEvenIfTreesWouldDiffer, [NotNullWhen(true)] out TreeAndVersion? newTreeAndVersion) { var siblingTree = siblingRoot.SyntaxTree; // Look for things that disqualify us from being able to use our sibling's root. - if (!CanReuseSiblingRoot()) + if (!CanReuseSiblingRoot(forceEvenIfTreesWouldDiffer)) { newTreeAndVersion = null; return false; @@ -128,8 +133,12 @@ static bool TryReuseSiblingRoot( // Note: we deliberately do not look at language version because it often is different across project // flavors. So we would often get no benefit to sharing if we restricted to only when the lang version // is the same. - bool CanReuseSiblingRoot() + bool CanReuseSiblingRoot(bool forceEvenIfTreesWouldDiffer) { + // If we're forcing reuse of a sibling tree, then this always succeeds. + if (forceEvenIfTreesWouldDiffer) + return true; + Interlocked.Increment(ref s_tryReuseSyntaxTree); var siblingParseOptions = siblingTree.Options; @@ -179,6 +188,7 @@ static async Task TryReuseSiblingTreeAsync( AsyncLazy treeSource, ITextAndVersionSource siblingTextSource, AsyncLazy siblingTreeSource, + bool forceEvenIfTreesWouldDiffer, CancellationToken cancellationToken) { var siblingTreeAndVersion = await siblingTreeSource.GetValueAsync(cancellationToken).ConfigureAwait(false); @@ -186,7 +196,7 @@ static async Task TryReuseSiblingTreeAsync( var siblingRoot = await siblingTree.GetRootAsync(cancellationToken).ConfigureAwait(false); - if (TryReuseSiblingRoot(filePath, languageServices, loadTextOptions, parseOptions, siblingRoot, siblingTreeAndVersion.Version, out var newTreeAndVersion)) + if (TryReuseSiblingRoot(filePath, languageServices, loadTextOptions, parseOptions, siblingRoot, siblingTreeAndVersion.Version, forceEvenIfTreesWouldDiffer, out var newTreeAndVersion)) return newTreeAndVersion; // Couldn't use the sibling file to get the tree contents. Instead, incrementally parse our tree to the text passed in. @@ -201,6 +211,7 @@ static TreeAndVersion TryReuseSiblingTree( AsyncLazy treeSource, ITextAndVersionSource siblingTextSource, AsyncLazy siblingTreeSource, + bool forceEvenIfTreesWouldDiffer, CancellationToken cancellationToken) { var siblingTreeAndVersion = siblingTreeSource.GetValue(cancellationToken); @@ -208,7 +219,7 @@ static TreeAndVersion TryReuseSiblingTree( var siblingRoot = siblingTree.GetRoot(cancellationToken); - if (TryReuseSiblingRoot(filePath, languageServices, loadTextOptions, parseOptions, siblingRoot, siblingTreeAndVersion.Version, out var newTreeAndVersion)) + if (TryReuseSiblingRoot(filePath, languageServices, loadTextOptions, parseOptions, siblingRoot, siblingTreeAndVersion.Version, forceEvenIfTreesWouldDiffer, out var newTreeAndVersion)) return newTreeAndVersion; // Couldn't use the sibling file to get the tree contents. Instead, incrementally parse our tree to the text passed in. diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Project.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Project.cs index 2b373931f72d8..dcce5bdc8d9a6 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Project.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Project.cs @@ -485,7 +485,7 @@ public bool TryGetCompilation([NotNullWhen(returnValue: true)] out Compilation? /// Determines if the compilation returned by and all its referenced compilation are from fully loaded projects. /// // TODO: make this public - internal Task HasSuccessfullyLoadedAsync(CancellationToken cancellationToken = default) + internal Task HasSuccessfullyLoadedAsync(CancellationToken cancellationToken) => _solution.CompilationState.HasSuccessfullyLoadedAsync(_projectState, cancellationToken); /// diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs index 04ed34a026113..d95db64d5da38 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs @@ -24,12 +24,22 @@ namespace Microsoft.CodeAnalysis [DataContract] public sealed class ProjectId : IEquatable { + /// + /// Checksum of this ProjectId, built only from . + /// + private SingleInitNullable _lazyChecksum; + /// /// The system generated unique id. /// [DataMember(Order = 0)] public Guid Id { get; } + /// + /// An optional name to show only for debugger-display purposes. This must not be used for any other + /// purpose. Importantly, it must not be part of the equality/hashing contract of this type (including ). + /// [DataMember(Order = 1)] private readonly string? _debugName; @@ -68,11 +78,8 @@ public override bool Equals(object? obj) => this.Equals(obj as ProjectId); public bool Equals(ProjectId? other) - { - return - other is object && + => other is not null && this.Id == other.Id; - } public static bool operator ==(ProjectId? left, ProjectId? right) => EqualityComparer.Default.Equals(left, right); @@ -96,5 +103,16 @@ internal static ProjectId ReadFrom(ObjectReader reader) return CreateFromSerialized(guid, debugName); } + + internal Checksum Checksum + => _lazyChecksum.Initialize(static @this => Checksum.Create(@this, + static (@this, writer) => + { + // Combine "ProjectId" string and guid. That way in the off chance that something in the stack uses + // the same Guid for something like a Solution or Document, that we'll still consider the checksums + // different. + writer.WriteString(nameof(ProjectId)); + writer.WriteGuid(@this.Id); + }), this); } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs index 38be03c2e5929..78c17a2ba6cb5 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs @@ -608,9 +608,9 @@ public static ProjectAttributes ReadFrom(ObjectReader reader) var projectId = ProjectId.ReadFrom(reader); // var version = VersionStamp.ReadFrom(reader); - var name = reader.ReadString(); - var assemblyName = reader.ReadString(); - var language = reader.ReadString(); + var name = reader.ReadRequiredString(); + var assemblyName = reader.ReadRequiredString(); + var language = reader.ReadRequiredString(); var filePath = reader.ReadString(); var outputFilePath = reader.ReadString(); var outputRefFilePath = reader.ReadString(); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs index 6ba5d342249c9..48aae6e7c3d7f 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Solution.cs @@ -1345,9 +1345,9 @@ public Solution WithDocumentSyntaxRoot(DocumentId documentId, SyntaxNode root, P return newCompilationState == _compilationState ? this : new Solution(newCompilationState); } - internal Solution WithDocumentContentsFrom(DocumentId documentId, DocumentState documentState) + internal Solution WithDocumentContentsFrom(DocumentId documentId, DocumentState documentState, bool forceEvenIfTreesWouldDiffer) { - var newCompilationState = _compilationState.WithDocumentContentsFrom(documentId, documentState); + var newCompilationState = _compilationState.WithDocumentContentsFrom(documentId, documentState, forceEvenIfTreesWouldDiffer); return newCompilationState == _compilationState ? this : new Solution(newCompilationState); } @@ -1442,16 +1442,15 @@ public Solution WithAnalyzerConfigDocumentTextLoader(DocumentId documentId, Text } /// - /// Creates a branch of the solution that has its compilations frozen in whatever state they are in at the time, assuming a background compiler is - /// busy building this compilations. - /// - /// A compilation for the project containing the specified document id will be guaranteed to exist with at least the syntax tree for the document. - /// - /// This not intended to be the public API, use Document.WithFrozenPartialSemantics() instead. + /// Creates a branch of the solution that has its compilations frozen in whatever state they are in at the time, + /// assuming a background compiler is busy building this compilations. + /// A compilation for the project containing the specified document id will be guaranteed to exist with + /// at least the syntax tree for the document. + /// This not intended to be the public API, use Document.WithFrozenPartialSemantics() instead. /// internal Solution WithFrozenPartialCompilationIncludingSpecificDocument(DocumentId documentId, CancellationToken cancellationToken) { - var newCompilationState = _compilationState.WithFrozenPartialCompilationIncludingSpecificDocument(documentId, cancellationToken); + var newCompilationState = this.CompilationState.WithFrozenPartialCompilationIncludingSpecificDocument(documentId, cancellationToken); return new Solution(newCompilationState); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction.cs index ceb53cbb3e325..528645b6012f6 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction.cs @@ -32,7 +32,7 @@ public virtual Task TransformCompilationAsync(Compilation oldCompil /// public abstract bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput { get; } - public virtual GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) => generatorDriver; + public abstract GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver); /// /// When changes are made to a solution, we make a list of translation actions. If multiple similar changes happen in rapid diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction_Actions.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction_Actions.cs index 0ca09911f0e44..423c74f3419b3 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction_Actions.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationAndGeneratorDriverTranslationAction_Actions.cs @@ -33,6 +33,9 @@ await _oldState.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false), // compilations that have generated trees. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) + => generatorDriver; + public override CompilationAndGeneratorDriverTranslationAction? TryMergeWithPrior(CompilationAndGeneratorDriverTranslationAction priorAction) { if (priorAction is TouchDocumentAction priorTouchAction && @@ -66,7 +69,7 @@ internal sealed class TouchAdditionalDocumentAction(AdditionalDocumentState oldS return null; } - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) { var oldText = _oldState.AdditionalText; var newText = _newState.AdditionalText; @@ -91,6 +94,9 @@ public override async Task TransformCompilationAsync(Compilation ol // This action removes the specified trees, but leaves the generated trees untouched. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; + + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) + => generatorDriver; } internal sealed class AddDocumentsAction(ImmutableArray documents) : CompilationAndGeneratorDriverTranslationAction @@ -109,6 +115,9 @@ public override async Task TransformCompilationAsync(Compilation ol // This action adds the specified trees, but leaves the generated trees untouched. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; + + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) + => generatorDriver; } internal sealed class ReplaceAllSyntaxTreesAction(ProjectState state, bool isParseOptionChange) : CompilationAndGeneratorDriverTranslationAction @@ -129,7 +138,7 @@ public override async Task TransformCompilationAsync(Compilation ol // Because this removes all trees, it'd also remove the generated trees. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => false; - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) { if (isParseOptionChange) { @@ -157,7 +166,7 @@ public override Task TransformCompilationAsync(Compilation oldCompi // compilations with stale generated trees. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) { if (isAnalyzerConfigChange) { @@ -182,6 +191,9 @@ public override Task TransformCompilationAsync(Compilation oldCompi // Updating the options of a compilation doesn't require us to reparse trees, so we can use this to update // compilations with stale generated trees. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; + + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) + => generatorDriver; } internal sealed class AddOrRemoveAnalyzerReferencesAction(string language, ImmutableArray referencesToAdd = default, ImmutableArray referencesToRemove = default) : CompilationAndGeneratorDriverTranslationAction @@ -192,7 +204,7 @@ internal sealed class AddOrRemoveAnalyzerReferencesAction(string language, Immut // the compilation with stale trees around, answering true is still important. public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) { if (!referencesToRemove.IsDefaultOrEmpty) { @@ -216,7 +228,7 @@ internal sealed class AddAdditionalDocumentsAction(ImmutableArray true; - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) { return generatorDriver.AddAdditionalTexts(additionalDocuments.SelectAsArray(static documentState => documentState.AdditionalText)); } @@ -230,7 +242,7 @@ internal sealed class RemoveAdditionalDocumentsAction(ImmutableArray true; - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver generatorDriver) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver generatorDriver) { return generatorDriver.RemoveAdditionalTexts(additionalDocuments.SelectAsArray(static documentState => documentState.AdditionalText)); } @@ -240,14 +252,15 @@ internal sealed class ReplaceGeneratorDriverAction(GeneratorDriver oldGeneratorD { public override bool CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput => true; - public override GeneratorDriver? TransformGeneratorDriver(GeneratorDriver _) + public override GeneratorDriver TransformGeneratorDriver(GeneratorDriver _) { // The GeneratorDriver that we have here is from a prior version of the Project, it may be missing state changes due // to changes to the project. We'll update everything here. - var generatorDriver = oldGeneratorDriver.ReplaceAdditionalTexts(newProjectState.AdditionalDocumentStates.SelectAsArray(static documentState => documentState.AdditionalText)) - .WithUpdatedParseOptions(newProjectState.ParseOptions!) - .WithUpdatedAnalyzerConfigOptions(newProjectState.AnalyzerOptions.AnalyzerConfigOptionsProvider) - .ReplaceGenerators(newProjectState.SourceGenerators.ToImmutableArray()); + var generatorDriver = oldGeneratorDriver + .ReplaceAdditionalTexts(newProjectState.AdditionalDocumentStates.SelectAsArray(static documentState => documentState.AdditionalText)) + .WithUpdatedParseOptions(newProjectState.ParseOptions!) + .WithUpdatedAnalyzerConfigOptions(newProjectState.AnalyzerOptions.AnalyzerConfigOptionsProvider) + .ReplaceGenerators(newProjectState.SourceGenerators.ToImmutableArray()); return generatorDriver; } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.CompilationTrackerState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.CompilationTrackerState.cs index 4546168a3bcf2..ac77cbfa9c05f 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.CompilationTrackerState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.CompilationTrackerState.cs @@ -16,35 +16,18 @@ internal partial class SolutionCompilationState { private partial class CompilationTracker { - private readonly struct CompilationTrackerGeneratorInfo + /// + /// The base type of all states. The state of a starts at null, and then will progress through the other states until it + /// finally reaches . + /// + private abstract class CompilationTrackerState { /// - /// The best generated documents we have for the current state. - /// specifies whether the documents are to be considered final and can be reused, or whether they're from - /// a prior snapshot which needs to be recomputed. - /// - public readonly TextDocumentStates Documents; - - /// - /// The that was used for the last run, to allow for incremental reuse. May - /// be null if we don't have generators in the first place, haven't ran generators yet for this project, - /// or had to get rid of our driver for some reason. - /// - public readonly GeneratorDriver? Driver; - - /// - /// Whether the generated documents in are final and should not be regenerated. - /// It's important that once we've ran generators once we don't want to run them again. Once we've ran - /// them the first time, those syntax trees are visible from other parts of the Workspaces model; if we - /// run them a second time we'd end up with new trees which would confuse our snapshot model -- once the - /// tree has been handed out we can't make a second tree later. - /// - public readonly bool DocumentsAreFinal; - - /// - /// Whether the generated documents are frozen and generators should never be ran again, ever, even if a document - /// is later changed. This is used to ensure that when we produce a frozen solution for partial semantics, - /// further downstream forking of that solution won't rerun generators. This is because of two reasons: + /// Whether the generated documents in are frozen and generators should + /// never be ran again, ever, even if a document is later changed. This is used to ensure that when we + /// produce a frozen solution for partial semantics, further downstream forking of that solution won't + /// rerun generators. This is because of two reasons: /// /// Generally once we've produced a frozen solution with partial semantics, we now want speed rather /// than accuracy; a generator running in a later path will still cause issues there. @@ -53,133 +36,105 @@ private readonly struct CompilationTrackerGeneratorInfo /// than what we originally had. /// /// - public readonly bool DocumentsAreFinalAndFrozen; - - public CompilationTrackerGeneratorInfo( - TextDocumentStates documents, - GeneratorDriver? driver, - bool documentsAreFinal, - bool documentsAreFinalAndFrozen = false) - { - Documents = documents; - Driver = driver; - DocumentsAreFinal = documentsAreFinal; - DocumentsAreFinalAndFrozen = documentsAreFinalAndFrozen; - - // If we're frozen, that implies final as well - Contract.ThrowIfTrue(documentsAreFinalAndFrozen && !documentsAreFinal); - } - - public CompilationTrackerGeneratorInfo WithDocumentsAreFinal(bool documentsAreFinal) - { - // If we're already frozen, then we won't do anything even if somebody calls WithDocumentsAreFinal(false); - // this for example would happen if we had a frozen snapshot, and then we fork it further with additional changes. - // In that case we would be calling WithDocumentsAreFinal(false) to force generators to run again, but if we've - // frozen in partial semantics, we're done running them period. So we'll just keep treating them as final, - // no matter the wishes of the caller. - if (DocumentsAreFinalAndFrozen || DocumentsAreFinal == documentsAreFinal) - return this; - else - return new(Documents, Driver, documentsAreFinal); - } - - public CompilationTrackerGeneratorInfo WithDocumentsAreFinalAndFrozen() - { - return DocumentsAreFinalAndFrozen ? this : new(Documents, Driver, documentsAreFinal: true, documentsAreFinalAndFrozen: true); - } - - public CompilationTrackerGeneratorInfo WithDriver(GeneratorDriver? driver) - => Driver == driver ? this : new(Documents, driver, DocumentsAreFinal, DocumentsAreFinalAndFrozen); - } - - /// - /// The base type of all states. The state of a - /// starts at , and then will progress through the other states until it finally reaches - /// . - /// - private abstract class CompilationTrackerState - { - /// - /// The base that starts with everything empty. - /// - public static readonly CompilationTrackerState Empty = new NoCompilationState( - new CompilationTrackerGeneratorInfo( - documents: TextDocumentStates.Empty, - driver: null, - documentsAreFinal: false)); + public readonly bool IsFrozen; /// /// The best compilation that is available that source generators have not ran on. May be an - /// in-progress, full declaration, a final compilation, or . + /// in-progress, full declaration, a final compilation. /// - public Compilation? CompilationWithoutGeneratedDocuments { get; } + public Compilation CompilationWithoutGeneratedDocuments { get; } public CompilationTrackerGeneratorInfo GeneratorInfo { get; } - /// - /// Specifies whether and all compilations it depends on contain full information or not. This can return - /// if the state isn't at the point where it would know, and it's necessary to transition to to figure that out. - /// - public virtual bool? HasSuccessfullyLoaded => null; - - /// - /// The final compilation is potentially available, otherwise . - /// - public virtual Compilation? FinalCompilationWithGeneratedDocuments => null; - protected CompilationTrackerState( - Compilation? compilationWithoutGeneratedDocuments, + bool isFrozen, + Compilation compilationWithoutGeneratedDocuments, CompilationTrackerGeneratorInfo generatorInfo) { + IsFrozen = isFrozen; CompilationWithoutGeneratedDocuments = compilationWithoutGeneratedDocuments; GeneratorInfo = generatorInfo; -#if DEBUG - - // As a sanity check, we should never see the generated trees inside of the compilation that should not - // have generated trees. - var compilation = compilationWithoutGeneratedDocuments; + // When in the frozen state, all documents must be final. We never want to run generators for frozen + // states as the point is to be fast (while potentially incomplete). + if (IsFrozen) + Contract.ThrowIfFalse(generatorInfo.DocumentsAreFinal); - if (compilation != null) +#if DEBUG + // As a sanity check, we should never see the generated trees inside of the compilation that should + // not have generated trees. + foreach (var generatedDocument in generatorInfo.Documents.States.Values) { - foreach (var generatedDocument in generatorInfo.Documents.States.Values) - { - Contract.ThrowIfTrue(compilation.SyntaxTrees.Contains(generatedDocument.GetSyntaxTree(CancellationToken.None))); - } + Contract.ThrowIfTrue(compilationWithoutGeneratedDocuments.SyntaxTrees.Contains(generatedDocument.GetSyntaxTree(CancellationToken.None))); } #endif } - public static CompilationTrackerState Create( - Compilation compilation, + /// + /// Returns a if is + /// empty, otherwise a . + /// + public static NonFinalWithCompilationTrackerState Create( + bool isFrozen, + Compilation compilationWithoutGeneratedDocuments, CompilationTrackerGeneratorInfo generatorInfo, - Compilation? compilationWithGeneratedDocuments, + Compilation? staleCompilationWithGeneratedDocuments, ImmutableList<(ProjectState state, CompilationAndGeneratorDriverTranslationAction action)> intermediateProjects) { Contract.ThrowIfTrue(intermediateProjects is null); + // If we're not frozen, transition back to the non-final state as we def want to rerun generators + // for either of these non-final states. + if (!isFrozen) + generatorInfo = generatorInfo with { DocumentsAreFinal = false }; + // If we don't have any intermediate projects to process, just initialize our // DeclarationState now. We'll pass false for generatedDocumentsAreFinal because this is being called // if our referenced projects are changing, so we'll have to rerun to consume changes. return intermediateProjects.IsEmpty - ? new AllSyntaxTreesParsedState(compilation, generatorInfo.WithDocumentsAreFinal(false)) - : new InProgressState(compilation, generatorInfo, compilationWithGeneratedDocuments, intermediateProjects); + ? new AllSyntaxTreesParsedState(isFrozen, compilationWithoutGeneratedDocuments, generatorInfo, staleCompilationWithGeneratedDocuments) + : new InProgressState(isFrozen, compilationWithoutGeneratedDocuments, generatorInfo, staleCompilationWithGeneratedDocuments, intermediateProjects); } } /// - /// State used when we potentially have some information (like prior generated documents) - /// but no compilation. + /// Root type for all compilation tracker that have a compilation, but are not the final /// - private sealed class NoCompilationState(CompilationTrackerGeneratorInfo generatorInfo) : CompilationTrackerState(compilationWithoutGeneratedDocuments: null, generatorInfo) + private abstract class NonFinalWithCompilationTrackerState : CompilationTrackerState { + /// + /// The result of taking the original completed compilation that had generated documents and updating + /// them by apply the ; this is not a + /// correct snapshot in that the generators have not been rerun, but may be reusable if the generators + /// are later found to give the same output. + /// + public Compilation? StaleCompilationWithGeneratedDocuments { get; } + + protected NonFinalWithCompilationTrackerState( + bool isFrozen, + Compilation compilationWithoutGeneratedDocuments, + CompilationTrackerGeneratorInfo generatorInfo, + Compilation? staleCompilationWithGeneratedDocuments) + : base(isFrozen, compilationWithoutGeneratedDocuments, generatorInfo) + { + // We're the non-final state. As such, there is a strong correspondence between these two pieces of + // state. Specifically, if we're frozen, then the documents must be final. After all, we do not + // want to generate SG docs in the frozen state. Conversely, if we're not frozen, the documents + // must not be final. We *must* generate the final docs from this state to get into the + // FinalCompilationTrackerState. + + Contract.ThrowIfFalse(IsFrozen == generatorInfo.DocumentsAreFinal); + + StaleCompilationWithGeneratedDocuments = staleCompilationWithGeneratedDocuments; + } } /// /// A state where we are holding onto a previously built compilation, and have a known set of transformations /// that could get us to a more final state. /// - private sealed class InProgressState : CompilationTrackerState + private sealed class InProgressState : NonFinalWithCompilationTrackerState { /// /// The list of changes that have happened since we last computed a compilation. The oldState corresponds to @@ -187,51 +142,60 @@ private sealed class InProgressState : CompilationTrackerState /// public ImmutableList<(ProjectState oldState, CompilationAndGeneratorDriverTranslationAction action)> IntermediateProjects { get; } - /// - /// The result of taking the original completed compilation that had generated documents and updating them by - /// apply the ; this is not a correct snapshot in that - /// the generators have not been rerun, but may be reusable if the generators are later found to give the - /// same output. - /// - public Compilation? CompilationWithGeneratedDocuments { get; } - public InProgressState( - Compilation inProgressCompilation, + bool isFrozen, + Compilation compilationWithoutGeneratedDocuments, CompilationTrackerGeneratorInfo generatorInfo, - Compilation? compilationWithGeneratedDocuments, + Compilation? staleCompilationWithGeneratedDocuments, ImmutableList<(ProjectState state, CompilationAndGeneratorDriverTranslationAction action)> intermediateProjects) - : base(compilationWithoutGeneratedDocuments: inProgressCompilation, - generatorInfo.WithDocumentsAreFinal(false)) // since we have a set of transformations to make, we'll always have to run generators again + : base(isFrozen, + compilationWithoutGeneratedDocuments, + generatorInfo, + staleCompilationWithGeneratedDocuments) { Contract.ThrowIfTrue(intermediateProjects is null); - Contract.ThrowIfFalse(intermediateProjects.Count > 0); + Contract.ThrowIfTrue(intermediateProjects.IsEmpty); - this.IntermediateProjects = intermediateProjects; - this.CompilationWithGeneratedDocuments = compilationWithGeneratedDocuments; + IntermediateProjects = intermediateProjects; } } /// - /// A built compilation for the tracker that contains the fully built DeclarationTable, - /// but may not have references initialized + /// A built compilation for the tracker that contains the fully built DeclarationTable, but may not have + /// references initialized. Note: this is practically the same as except that + /// there are no intermediary translation actions to apply. The tracker state always moves into this state + /// prior to moving to the . /// - private sealed class AllSyntaxTreesParsedState(Compilation declarationCompilation, CompilationTrackerGeneratorInfo generatorInfo) : CompilationTrackerState(declarationCompilation, generatorInfo) + private sealed class AllSyntaxTreesParsedState( + bool isFrozen, + Compilation compilationWithoutGeneratedDocuments, + CompilationTrackerGeneratorInfo generatorInfo, + Compilation? staleCompilationWithGeneratedDocuments) : NonFinalWithCompilationTrackerState( + isFrozen, + compilationWithoutGeneratedDocuments, + generatorInfo, + staleCompilationWithGeneratedDocuments) { } /// - /// The final state a compilation tracker reaches. The real is available. It is a - /// requirement that any provided to any clients of the - /// (for example, through or must be from a . This is because stores extra information in it about that compilation that the can be queried for (for example: . If s from other s are passed out, then these other APIs will not function correctly. + /// The final state a compilation tracker reaches. At this point is now available. It is a requirement that any provided to any clients of the (for example, through + /// or must be from a . This is because + /// stores extra information in it about that compilation that the can be + /// queried for (for example: . If s from other s are passed out, then these other + /// APIs will not function correctly. /// - private sealed class FinalState : CompilationTrackerState + private sealed class FinalCompilationTrackerState : CompilationTrackerState { - public override bool? HasSuccessfullyLoaded { get; } + /// + /// Specifies whether and all compilations it + /// depends on contain full information or not. + /// + public readonly bool HasSuccessfullyLoaded; /// /// Weak set of the assembly, module and dynamic symbols that this compilation tracker has created. @@ -243,26 +207,27 @@ private sealed class FinalState : CompilationTrackerState /// /// The final compilation, with all references and source generators run. This is distinct from , which in the case will be the compilation before any - /// source generators were ran. This ensures that a later invocation of the source generators consumes - /// which will avoid generators being ran a second time on a compilation that - /// already contains the output of other generators. If source generators are not active, this is equal - /// to . + /// cref="Compilation"/>, which in the case will be the + /// compilation before any source generators were ran. This ensures that a later invocation of the + /// source generators consumes which will avoid generators being ran a second + /// time on a compilation that already contains the output of other generators. If source generators are + /// not active, this is equal to . /// - public override Compilation FinalCompilationWithGeneratedDocuments { get; } + public readonly Compilation FinalCompilationWithGeneratedDocuments; - private FinalState( - Compilation finalCompilation, - Compilation compilationWithoutGeneratedFiles, + private FinalCompilationTrackerState( + bool isFrozen, + Compilation finalCompilationWithGeneratedDocuments, + Compilation compilationWithoutGeneratedDocuments, bool hasSuccessfullyLoaded, CompilationTrackerGeneratorInfo generatorInfo, UnrootedSymbolSet unrootedSymbolSet) - : base(compilationWithoutGeneratedFiles, - generatorInfo.WithDocumentsAreFinal(true)) // when we're in a final state, we've ran generators and should not run again + : base(isFrozen, compilationWithoutGeneratedDocuments, generatorInfo) { - Contract.ThrowIfNull(finalCompilation); + Contract.ThrowIfFalse(generatorInfo.DocumentsAreFinal); + Contract.ThrowIfNull(finalCompilationWithGeneratedDocuments); HasSuccessfullyLoaded = hasSuccessfullyLoaded; - FinalCompilationWithGeneratedDocuments = finalCompilation; + FinalCompilationWithGeneratedDocuments = finalCompilationWithGeneratedDocuments; UnrootedSymbolSet = unrootedSymbolSet; if (this.GeneratorInfo.Documents.IsEmpty) @@ -270,31 +235,33 @@ private FinalState( // If we have no generated files, the pre-generator compilation and post-generator compilation // should be the exact same instance; that way we're not creating more compilations than // necessary that would be unable to share source symbols. - Debug.Assert(object.ReferenceEquals(finalCompilation, compilationWithoutGeneratedFiles)); + Debug.Assert(object.ReferenceEquals(finalCompilationWithGeneratedDocuments, compilationWithoutGeneratedDocuments)); } } - /// Not held onto /// Not held onto /// Not held onto - public static FinalState Create( - Compilation finalCompilationSource, - Compilation compilationWithoutGeneratedFiles, + public static FinalCompilationTrackerState Create( + bool isFrozen, + Compilation finalCompilationWithGeneratedDocuments, + Compilation compilationWithoutGeneratedDocuments, bool hasSuccessfullyLoaded, CompilationTrackerGeneratorInfo generatorInfo, - Compilation finalCompilation, ProjectId projectId, Dictionary? metadataReferenceToProjectId) { + Contract.ThrowIfFalse(generatorInfo.DocumentsAreFinal); + // Keep track of information about symbols from this Compilation. This will help support other APIs // the solution exposes that allows the user to map back from symbols to project information. - var unrootedSymbolSet = UnrootedSymbolSet.Create(finalCompilation); - RecordAssemblySymbols(projectId, finalCompilation, metadataReferenceToProjectId); + var unrootedSymbolSet = UnrootedSymbolSet.Create(finalCompilationWithGeneratedDocuments); + RecordAssemblySymbols(projectId, finalCompilationWithGeneratedDocuments, metadataReferenceToProjectId); - return new FinalState( - finalCompilationSource, - compilationWithoutGeneratedFiles, + return new FinalCompilationTrackerState( + isFrozen, + finalCompilationWithGeneratedDocuments, + compilationWithoutGeneratedDocuments, hasSuccessfullyLoaded, generatorInfo, unrootedSymbolSet); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.cs index 37050cc565293..33c8dd97b3232 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker.cs @@ -11,14 +11,11 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.Logging; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Collections; -using Microsoft.CodeAnalysis.SourceGeneratorTelemetry; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis @@ -40,7 +37,7 @@ private partial class CompilationTracker : ICompilationTracker /// /// Access via the and methods. /// - private CompilationTrackerState _stateDoNotAccessDirectly; + private CompilationTrackerState? _stateDoNotAccessDirectly; // guarantees only one thread is building at a time private readonly SemaphoreSlim _buildLock = new(initialCount: 1); @@ -55,7 +52,7 @@ private partial class CompilationTracker : ICompilationTracker private CompilationTracker( ProjectState project, - CompilationTrackerState state, + CompilationTrackerState? state, SkeletonReferenceCache cachedSkeletonReferences) { Contract.ThrowIfNull(project); @@ -74,11 +71,11 @@ private CompilationTracker( /// and will have no extra information beyond the project itself. /// public CompilationTracker(ProjectState project) - : this(project, CompilationTrackerState.Empty, cachedSkeletonReferences: new()) + : this(project, state: null, cachedSkeletonReferences: new()) { } - private CompilationTrackerState ReadState() + private CompilationTrackerState? ReadState() => Volatile.Read(ref _stateDoNotAccessDirectly); private void WriteState(CompilationTrackerState state) @@ -92,7 +89,7 @@ public GeneratorDriver? GeneratorDriver get { var state = this.ReadState(); - return state.GeneratorInfo.Driver; + return state?.GeneratorInfo.Driver; } } @@ -103,7 +100,7 @@ SymbolKind.NetModule or SymbolKind.DynamicType); var state = this.ReadState(); - var unrootedSymbolSet = (state as FinalState)?.UnrootedSymbolSet; + var unrootedSymbolSet = (state as FinalCompilationTrackerState)?.UnrootedSymbolSet; if (unrootedSymbolSet == null) { // this was not a tracker that has handed out a compilation (all compilations handed out must be @@ -119,60 +116,74 @@ SymbolKind.NetModule or /// compilation state as the now 'old' state /// public ICompilationTracker Fork( - ProjectState newProject, + ProjectState newProjectState, CompilationAndGeneratorDriverTranslationAction? translate) { - var state = ReadState(); - - var baseCompilation = state.CompilationWithoutGeneratedDocuments; - if (baseCompilation != null) + var forkedTrackerState = ForkTrackerState(oldProjectState: this.ProjectState, ReadState(), translate); + + // We should never fork into a FinalCompilationTrackerState. We must always be at some state prior to + // it since some change has happened, and we may now need to run generators. + Contract.ThrowIfTrue(forkedTrackerState is FinalCompilationTrackerState); + return new CompilationTracker( + newProjectState, + forkedTrackerState, + this.SkeletonReferenceCache.Clone()); + + static CompilationTrackerState? ForkTrackerState( + ProjectState oldProjectState, + CompilationTrackerState? state, + CompilationAndGeneratorDriverTranslationAction? translate) { - var intermediateProjects = state is InProgressState inProgressState - ? inProgressState.IntermediateProjects - : []; + if (state is null) + return null; - if (translate is not null) + // Determine the old/stale compilation to help seed the non-final state with. + var staleCompilationWithGeneratedDocuments = state switch { - // We have a translation action; are we able to merge it with the prior one? - var merged = false; - if (intermediateProjects.Any()) - { - var (priorState, priorAction) = intermediateProjects.Last(); - var mergedTranslation = translate.TryMergeWithPrior(priorAction); - if (mergedTranslation != null) - { - // We can replace the prior action with this new one - intermediateProjects = intermediateProjects.SetItem(intermediateProjects.Count - 1, - (oldState: priorState, mergedTranslation)); - merged = true; - } - } + FinalCompilationTrackerState finalState => finalState.FinalCompilationWithGeneratedDocuments, + NonFinalWithCompilationTrackerState nonFinalState => nonFinalState.StaleCompilationWithGeneratedDocuments, + _ => throw ExceptionUtilities.UnexpectedValue(state.GetType()), + }; - if (!merged) - { - // Just add it to the end - intermediateProjects = intermediateProjects.Add((oldState: this.ProjectState, translate)); - } - } + var intermediateProjects = UpdateIntermediateProjects(oldProjectState, state, translate); var newState = CompilationTrackerState.Create( - baseCompilation, state.GeneratorInfo, state.FinalCompilationWithGeneratedDocuments, intermediateProjects); - - return new CompilationTracker(newProject, newState, this.SkeletonReferenceCache.Clone()); + state.IsFrozen, + state.CompilationWithoutGeneratedDocuments, + state.GeneratorInfo, + staleCompilationWithGeneratedDocuments, + intermediateProjects); + return newState; } - else + + static ImmutableList<(ProjectState oldState, CompilationAndGeneratorDriverTranslationAction action)> UpdateIntermediateProjects( + ProjectState oldProjectState, + CompilationTrackerState state, + CompilationAndGeneratorDriverTranslationAction? translate) { - // We may still have a cached generator; we'll have to remember to run generators again since we are making some - // change here. We'll also need to update the other state of the driver if appropriate. - var generatorInfo = state.GeneratorInfo.WithDocumentsAreFinal(false); + var intermediateProjects = state is InProgressState inProgressState + ? inProgressState.IntermediateProjects + : []; + + if (translate is null) + return intermediateProjects; - if (generatorInfo.Driver != null && translate != null) + // We have a translation action; are we able to merge it with the prior one? + if (!intermediateProjects.IsEmpty) { - generatorInfo = generatorInfo.WithDriver(translate.TransformGeneratorDriver(generatorInfo.Driver)); + var (priorState, priorAction) = intermediateProjects.Last(); + var mergedTranslation = translate.TryMergeWithPrior(priorAction); + if (mergedTranslation != null) + { + // We can replace the prior action with this new one + return intermediateProjects.SetItem( + intermediateProjects.Count - 1, + (oldState: priorState, mergedTranslation)); + } } - var newState = new NoCompilationState(generatorInfo); - return new CompilationTracker(newProject, newState, this.SkeletonReferenceCache.Clone()); + // Just add it to the end + return intermediateProjects.Add((oldProjectState, translate)); } } @@ -250,15 +261,18 @@ public ICompilationTracker FreezePartialStateWithTree( // At this point, we now absolutely should have our tree in the compilation Contract.ThrowIfFalse(compilationPair.CompilationWithoutGeneratedDocuments.ContainsSyntaxTree(tree)); - // The user is asking for an in progress snap. We don't want to create it and then - // have the compilation immediately disappear. So we force it to stay around with a ConstantValueSource. - // As a policy, all partial-state projects are said to have incomplete references, since the state has no guarantees. - var finalState = FinalState.Create( - finalCompilationSource: compilationPair.CompilationWithGeneratedDocuments, - compilationWithoutGeneratedFiles: compilationPair.CompilationWithoutGeneratedDocuments, + // Mark whatever generator state we have as not only final, and mark our FinalState as frozen as well. + // We'll want to keep whatever we have here through whatever future transformations occur. + generatorInfo = generatorInfo with { DocumentsAreFinal = true }; + + var finalState = FinalCompilationTrackerState.Create( + isFrozen: true, + finalCompilationWithGeneratedDocuments: compilationPair.CompilationWithGeneratedDocuments, + compilationWithoutGeneratedDocuments: compilationPair.CompilationWithoutGeneratedDocuments, + // As a policy, all partial-state projects are said to have incomplete references, since the state + // has no guarantees. hasSuccessfullyLoaded: false, generatorInfo, - finalCompilation: compilationPair.CompilationWithGeneratedDocuments, this.ProjectState.Id, metadataReferenceToProjectId); @@ -268,7 +282,7 @@ public ICompilationTracker FreezePartialStateWithTree( /// /// Tries to get the latest snapshot of the compilation without waiting for it to be fully built. This /// method takes advantage of the progress side-effect produced during . It will either return the already built compilation, any in-progress + /// cref="GetOrBuildFinalStateAsync"/>. It will either return the already built compilation, any in-progress /// compilation or any known old compilation in that order of preference. The compilation state that is /// returned will have a compilation that is retained so that it cannot disappear. /// @@ -282,12 +296,13 @@ private void GetPartialCompilationState( CancellationToken cancellationToken) { var state = ReadState(); - var compilationWithoutGeneratedDocuments = state.CompilationWithoutGeneratedDocuments; + var compilationWithoutGeneratedDocuments = state?.CompilationWithoutGeneratedDocuments; + + generatorInfo = state?.GeneratorInfo ?? CompilationTrackerGeneratorInfo.Empty; // check whether we can bail out quickly for typing case var inProgressState = state as InProgressState; - generatorInfo = state.GeneratorInfo.WithDocumentsAreFinalAndFrozen(); inProgressProject = inProgressState != null ? inProgressState.IntermediateProjects.First().oldState : this.ProjectState; // all changes left for this document is modifying the given document; since the compilation is already fully up to date @@ -305,12 +320,11 @@ private void GetPartialCompilationState( // This is likely a bug. It seems possible to pass out a partial compilation state that we don't // properly record assembly symbols for. metadataReferenceToProjectId = null; - SolutionLogger.UseExistingPartialProjectState(); return; } // if we already have a final compilation we are done. - if (compilationWithoutGeneratedDocuments != null && state is FinalState finalState) + if (compilationWithoutGeneratedDocuments != null && state is FinalCompilationTrackerState finalState) { var finalCompilation = finalState.FinalCompilationWithGeneratedDocuments; Contract.ThrowIfNull(finalCompilation, "We have a FinalState, so we must have a non-null final compilation"); @@ -322,7 +336,6 @@ private void GetPartialCompilationState( // again is likely ok (as long as compilations continue to return the same IAssemblySymbols for // the same references across source edits). metadataReferenceToProjectId = null; - SolutionLogger.UseExistingFullProjectState(); return; } @@ -393,8 +406,6 @@ private void GetPartialCompilationState( { compilations = compilations.WithReferences(metadataReferences); } - - SolutionLogger.CreatePartialProjectState(); } private static bool IsTouchDocumentActionForDocument(CompilationAndGeneratorDriverTranslationAction action, DocumentId id) @@ -407,8 +418,17 @@ private static bool IsTouchDocumentActionForDocument(CompilationAndGeneratorDriv public bool TryGetCompilation([NotNullWhen(true)] out Compilation? compilation) { var state = ReadState(); - compilation = state.FinalCompilationWithGeneratedDocuments; - return compilation != null; + if (state is FinalCompilationTrackerState finalState) + { + compilation = finalState.FinalCompilationWithGeneratedDocuments; + Contract.ThrowIfNull(compilation); + return true; + } + else + { + compilation = null; + return false; + } } public Task GetCompilationAsync(SolutionCompilationState compilationState, CancellationToken cancellationToken) @@ -433,13 +453,12 @@ public Task GetCompilationAsync(SolutionCompilationState compilatio private async Task GetCompilationSlowAsync( SolutionCompilationState compilationState, CancellationToken cancellationToken) { - var compilationInfo = await GetOrBuildCompilationInfoAsync(compilationState, lockGate: true, cancellationToken: cancellationToken).ConfigureAwait(false); - return compilationInfo.Compilation; + var finalState = await GetOrBuildFinalStateAsync(compilationState, cancellationToken: cancellationToken).ConfigureAwait(false); + return finalState.FinalCompilationWithGeneratedDocuments; } - private async Task GetOrBuildCompilationInfoAsync( + private async Task GetOrBuildFinalStateAsync( SolutionCompilationState compilationState, - bool lockGate, CancellationToken cancellationToken) { try @@ -452,25 +471,14 @@ private async Task GetOrBuildCompilationInfoAsync( var state = ReadState(); // Try to get the built compilation. If it exists, then we can just return that. - var finalCompilation = state.FinalCompilationWithGeneratedDocuments; - if (finalCompilation != null) - { - RoslynDebug.Assert(state.HasSuccessfullyLoaded.HasValue); - return new CompilationInfo(finalCompilation, state.HasSuccessfullyLoaded.Value, state.GeneratorInfo); - } + if (state is FinalCompilationTrackerState finalState) + return finalState; // Otherwise, we actually have to build it. Ensure that only one thread is trying to // build this compilation at a time. - if (lockGate) + using (await _buildLock.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { - using (await _buildLock.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) - { - return await BuildCompilationInfoAsync(compilationState, cancellationToken).ConfigureAwait(false); - } - } - else - { - return await BuildCompilationInfoAsync(compilationState, cancellationToken).ConfigureAwait(false); + return await BuildFinalStateAsync().ConfigureAwait(false); } } } @@ -478,350 +486,311 @@ private async Task GetOrBuildCompilationInfoAsync( { throw ExceptionUtilities.Unreachable(); } - } - /// - /// Builds the compilation matching the project state. In the process of building, also - /// produce in progress snapshots that can be accessed from other threads. - /// - private async Task BuildCompilationInfoAsync( - SolutionCompilationState compilationState, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); + // + // Builds the compilation matching the project state. In the process of building, also + // produce in progress snapshots that can be accessed from other threads. + // + async Task BuildFinalStateAsync() + { + cancellationToken.ThrowIfCancellationRequested(); - var state = ReadState(); + var state = ReadState(); - // if we already have a compilation, we must be already done! This can happen if two - // threads were waiting to build, and we came in after the other succeeded. - var compilation = state.FinalCompilationWithGeneratedDocuments; - if (compilation != null) - { - RoslynDebug.Assert(state.HasSuccessfullyLoaded.HasValue); - return new CompilationInfo(compilation, state.HasSuccessfullyLoaded.Value, state.GeneratorInfo); - } + // if we already have a compilation, we must be already done! This can happen if two + // threads were waiting to build, and we came in after the other succeeded. + if (state is FinalCompilationTrackerState finalState) + return finalState; - compilation = state.CompilationWithoutGeneratedDocuments; + // Transition from wherever we're currently at to the 'all trees parsed' state. + var allSyntaxTreesParsedState = state switch + { + // If we're already there, then there's nothing to do. + AllSyntaxTreesParsedState allParsedState => allParsedState, - if (compilation == null) - { - // We've got nothing. Build it from scratch :( - return await BuildCompilationInfoFromScratchAsync( - compilationState, - state.GeneratorInfo, - cancellationToken).ConfigureAwait(false); - } + // We've got nothing. Build it from scratch :( + null => await BuildAllSyntaxTreesParsedStateFromNoCompilationStateAsync().ConfigureAwait(false), - if (state is AllSyntaxTreesParsedState or FinalState) - { - // We have a declaration compilation, use it to reconstruct the final compilation - return await FinalizeCompilationAsync( - compilationState, - compilation, - state.GeneratorInfo, - compilationWithStaleGeneratedTrees: null, - cancellationToken).ConfigureAwait(false); - } - else - { - // We must have an in progress compilation. Build off of that. - return await BuildFinalStateFromInProgressStateAsync( - compilationState, (InProgressState)state, compilation, cancellationToken).ConfigureAwait(false); - } - } + // We must have an in progress compilation. Build off of that. + InProgressState inProgressState + => await BuildAllSyntaxTreesParsedStateFromInProgressStateAsync(inProgressState).ConfigureAwait(false), - private async Task BuildCompilationInfoFromScratchAsync( - SolutionCompilationState compilationState, - CompilationTrackerGeneratorInfo generatorInfo, - CancellationToken cancellationToken) - { - try - { - var compilation = await BuildDeclarationCompilationFromScratchAsync( - generatorInfo, cancellationToken).ConfigureAwait(false); - - return await FinalizeCompilationAsync( - compilationState, - compilation, - generatorInfo, - compilationWithStaleGeneratedTrees: null, - cancellationToken).ConfigureAwait(false); - } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) - { - throw ExceptionUtilities.Unreachable(); + _ => throw ExceptionUtilities.UnexpectedValue(state.GetType()) + }; + + // Now do the final step of transitioning from the 'all trees parsed' state to the final state. + return await FinalizeCompilationAsync(allSyntaxTreesParsedState).ConfigureAwait(false); } - } - [PerformanceSensitive( - "https://github.com/dotnet/roslyn/issues/23582", - Constraint = "Avoid calling " + nameof(Compilation.AddSyntaxTrees) + " in a loop due to allocation overhead.")] - private async Task BuildDeclarationCompilationFromScratchAsync( - CompilationTrackerGeneratorInfo generatorInfo, - CancellationToken cancellationToken) - { - try + [PerformanceSensitive( + "https://github.com/dotnet/roslyn/issues/23582", + Constraint = "Avoid calling " + nameof(Compilation.AddSyntaxTrees) + " in a loop due to allocation overhead.")] + async Task BuildAllSyntaxTreesParsedStateFromNoCompilationStateAsync() { - var compilation = CreateEmptyCompilation(); - - using var _ = ArrayBuilder.GetInstance(ProjectState.DocumentStates.Count, out var trees); - foreach (var documentState in ProjectState.DocumentStates.GetStatesInCompilationOrder()) + try { - cancellationToken.ThrowIfCancellationRequested(); - // Include the tree even if the content of the document failed to load. - trees.Add(await documentState.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)); - } + var compilation = CreateEmptyCompilation(); - compilation = compilation.AddSyntaxTrees(trees); - WriteState(new AllSyntaxTreesParsedState(compilation, generatorInfo)); - return compilation; - } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) - { - throw ExceptionUtilities.Unreachable(); - } - } + using var _ = ArrayBuilder.GetInstance(ProjectState.DocumentStates.Count, out var trees); + foreach (var documentState in ProjectState.DocumentStates.GetStatesInCompilationOrder()) + { + cancellationToken.ThrowIfCancellationRequested(); + // Include the tree even if the content of the document failed to load. + trees.Add(await documentState.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)); + } - private Compilation CreateEmptyCompilation() - { - var compilationFactory = this.ProjectState.LanguageServices.GetRequiredService(); + compilation = compilation.AddSyntaxTrees(trees); - if (this.ProjectState.IsSubmission) - { - return compilationFactory.CreateSubmissionCompilation( - this.ProjectState.AssemblyName, - this.ProjectState.CompilationOptions!, - this.ProjectState.HostObjectType); - } - else - { - return compilationFactory.CreateCompilation( - this.ProjectState.AssemblyName, - this.ProjectState.CompilationOptions!); + // We only got here when we had no compilation state at all. So we couldn't have gotten + // here from a frozen state (as a frozen state always ensures we have a + // WithCompilationTrackerState). As such, we can safely still preserve that we're not + // frozen here. + var allSyntaxTreesParsedState = new AllSyntaxTreesParsedState( + isFrozen: false, compilation, CompilationTrackerGeneratorInfo.Empty, staleCompilationWithGeneratedDocuments: null); + WriteState(allSyntaxTreesParsedState); + return allSyntaxTreesParsedState; + } + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) + { + throw ExceptionUtilities.Unreachable(); + } } - } - private async Task BuildFinalStateFromInProgressStateAsync( - SolutionCompilationState compilationState, InProgressState state, Compilation inProgressCompilation, CancellationToken cancellationToken) - { - try - { - var (compilationWithoutGenerators, compilationWithGenerators, generatorDriver) = await BuildDeclarationCompilationFromInProgressAsync( - state, inProgressCompilation, cancellationToken).ConfigureAwait(false); - - return await FinalizeCompilationAsync( - compilationState, - compilationWithoutGenerators, - state.GeneratorInfo.WithDriver(generatorDriver), - compilationWithGenerators, - cancellationToken).ConfigureAwait(false); - } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) + async Task BuildAllSyntaxTreesParsedStateFromInProgressStateAsync(InProgressState initialState) { - throw ExceptionUtilities.Unreachable(); - } - } + try + { + // This is guaranteed by an in progress state. Which means we know we'll get into the while loop below. + Contract.ThrowIfTrue(initialState.IntermediateProjects.IsEmpty); - private async Task<(Compilation compilationWithoutGenerators, Compilation? compilationWithGenerators, GeneratorDriver? generatorDriver)> BuildDeclarationCompilationFromInProgressAsync( - InProgressState state, Compilation compilationWithoutGenerators, CancellationToken cancellationToken) - { - try - { - var compilationWithGenerators = state.CompilationWithGeneratedDocuments; - var generatorDriver = state.GeneratorInfo.Driver; - - // If compilationWithGenerators is the same as compilationWithoutGenerators, then it means a prior run of generators - // didn't produce any files. In that case, we'll just make compilationWithGenerators null so we avoid doing any - // transformations of it multiple times. Otherwise the transformations below and in FinalizeCompilationAsync will try - // to update both at once, which is functionally fine but just unnecessary work. This function is always allowed to return - // null for compilationWithGenerators in the end, so there's no harm there. - if (compilationWithGenerators == compilationWithoutGenerators) + NonFinalWithCompilationTrackerState currentState = initialState; + while (currentState is InProgressState inProgressState) + { + cancellationToken.ThrowIfCancellationRequested(); + + // We have a list of transformations to get to our final compilation; take the first transformation and apply it. + var (compilationWithoutGeneratedDocuments, staleCompilationWithGeneratedDocuments, generatorInfo) = + await ApplyFirstTransformationAsync(inProgressState).ConfigureAwait(false); + + // We have updated state, so store this new result; this allows us to drop the intermediate state we already processed + // even if we were to get cancelled at a later point. + // + // As long as we have intermediate projects, we'll still keep creating InProgressStates. But + // once it becomes empty we'll produce an AllSyntaxTreesParsedState and we'll break the loop. + // + // Preserve the current frozen bit. Specifically, once states become frozen, we continually make + // all states forked from those states frozen as well. This ensures we don't attempt to move + // generator docs back to the uncomputed state from that point onwards. We'll just keep + // whateverZ generated docs we have. + currentState = CompilationTrackerState.Create( + inProgressState.IsFrozen, + compilationWithoutGeneratedDocuments, + generatorInfo, + staleCompilationWithGeneratedDocuments, + inProgressState.IntermediateProjects.RemoveAt(0)); + this.WriteState(currentState); + + Contract.ThrowIfTrue(inProgressState.IntermediateProjects.Count > 1 && currentState is not InProgressState); + Contract.ThrowIfTrue(inProgressState.IntermediateProjects.Count == 1 && currentState is not AllSyntaxTreesParsedState); + } + + Contract.ThrowIfTrue(currentState is not AllSyntaxTreesParsedState); + return (AllSyntaxTreesParsedState)currentState; + } + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) { - compilationWithGenerators = null; + throw ExceptionUtilities.Unreachable(); } - var intermediateProjects = state.IntermediateProjects; - - while (!intermediateProjects.IsEmpty) + async Task<(Compilation compilationWithoutGeneratedDocuments, Compilation? staleCompilationWithGeneratedDocuments, CompilationTrackerGeneratorInfo generatorInfo)> + ApplyFirstTransformationAsync(InProgressState inProgressState) { - cancellationToken.ThrowIfCancellationRequested(); + Contract.ThrowIfTrue(inProgressState.IntermediateProjects.IsEmpty); + var (oldState, action) = inProgressState.IntermediateProjects[0]; + + var compilationWithoutGeneratedDocuments = inProgressState.CompilationWithoutGeneratedDocuments; + var staleCompilationWithGeneratedDocuments = inProgressState.StaleCompilationWithGeneratedDocuments; - // We have a list of transformations to get to our final compilation; take the first transformation and apply it. - var intermediateProject = intermediateProjects[0]; + // If staleCompilationWithGeneratedDocuments is the same as compilationWithoutGeneratedDocuments, + // then it means a prior run of generators didn't produce any files. In that case, we'll just make + // staleCompilationWithGeneratedDocuments null so we avoid doing any transformations of it multiple + // times. Otherwise the transformations below and in FinalizeCompilationAsync will try to update + // both at once, which is functionally fine but just unnecessary work. This function is always + // allowed to return null for AllSyntaxTreesParsedState.StaleCompilationWithGeneratedDocuments in + // the end, so there's no harm there. + if (staleCompilationWithGeneratedDocuments == compilationWithoutGeneratedDocuments) + staleCompilationWithGeneratedDocuments = null; - compilationWithoutGenerators = await intermediateProject.action.TransformCompilationAsync(compilationWithoutGenerators, cancellationToken).ConfigureAwait(false); + compilationWithoutGeneratedDocuments = await action.TransformCompilationAsync(compilationWithoutGeneratedDocuments, cancellationToken).ConfigureAwait(false); - if (compilationWithGenerators != null) + if (staleCompilationWithGeneratedDocuments != null) { // Also transform the compilation that has generated files; we won't do that though if the transformation either would cause problems with // the generated documents, or if don't have any source generators in the first place. - if (intermediateProject.action.CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput && - intermediateProject.oldState.SourceGenerators.Any()) + if (action.CanUpdateCompilationWithStaleGeneratedTreesIfGeneratorsGiveSameOutput && + oldState.SourceGenerators.Any()) { - compilationWithGenerators = await intermediateProject.action.TransformCompilationAsync(compilationWithGenerators, cancellationToken).ConfigureAwait(false); + staleCompilationWithGeneratedDocuments = await action.TransformCompilationAsync(staleCompilationWithGeneratedDocuments, cancellationToken).ConfigureAwait(false); } else { - compilationWithGenerators = null; + staleCompilationWithGeneratedDocuments = null; } } - if (generatorDriver != null) - { - generatorDriver = intermediateProject.action.TransformGeneratorDriver(generatorDriver); - } - - // We have updated state, so store this new result; this allows us to drop the intermediate state we already processed - // even if we were to get cancelled at a later point. - intermediateProjects = intermediateProjects.RemoveAt(0); + var generatorInfo = inProgressState.GeneratorInfo; + if (generatorInfo.Driver != null) + generatorInfo = generatorInfo with { Driver = action.TransformGeneratorDriver(generatorInfo.Driver) }; - this.WriteState(CompilationTrackerState.Create( - compilationWithoutGenerators, state.GeneratorInfo.WithDriver(generatorDriver), compilationWithGenerators, intermediateProjects)); + return (compilationWithoutGeneratedDocuments, staleCompilationWithGeneratedDocuments, generatorInfo); } - - return (compilationWithoutGenerators, compilationWithGenerators, generatorDriver); } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) - { - throw ExceptionUtilities.Unreachable(); - } - } - - private readonly struct CompilationInfo(Compilation compilation, bool hasSuccessfullyLoaded, CompilationTrackerGeneratorInfo generatorInfo) - { - public Compilation Compilation { get; } = compilation; - public bool HasSuccessfullyLoaded { get; } = hasSuccessfullyLoaded; - public CompilationTrackerGeneratorInfo GeneratorInfo { get; } = generatorInfo; - } - /// - /// Add all appropriate references to the compilation and set it as our final compilation - /// state. - /// - /// The generator info that contains the last run of the documents, if any exists, as - /// well as the driver that can be used to run if need to. - /// The compilation from a prior run that contains generated trees, which - /// match the states included in . If a generator run here produces - /// the same set of generated documents as are in , and we don't need to make any other - /// changes to references, we can then use this compilation instead of re-adding source generated files again to the - /// . - private async Task FinalizeCompilationAsync( - SolutionCompilationState compilationState, - Compilation compilationWithoutGeneratedFiles, - CompilationTrackerGeneratorInfo generatorInfo, - Compilation? compilationWithStaleGeneratedTrees, - CancellationToken cancellationToken) - { - try + // + // Add all appropriate references to the compilation and set it as our final compilation state. + // + async Task FinalizeCompilationAsync( + AllSyntaxTreesParsedState allSyntaxTreesParsedState) { - // Project is complete only if the following are all true: - // 1. HasAllInformation flag is set for the project - // 2. Either the project has non-zero metadata references OR this is the corlib project. - // For the latter, we use a heuristic if the underlying compilation defines "System.Object" type. - var hasSuccessfullyLoaded = this.ProjectState.HasAllInformation && - (this.ProjectState.MetadataReferences.Count > 0 || - compilationWithoutGeneratedFiles.GetTypeByMetadataName("System.Object") != null); - - var newReferences = new List(); - var metadataReferenceToProjectId = new Dictionary(); - newReferences.AddRange(this.ProjectState.MetadataReferences); - - foreach (var projectReference in this.ProjectState.ProjectReferences) + try { - var referencedProject = compilationState.SolutionState.GetProjectState(projectReference.ProjectId); - - // Even though we're creating a final compilation (vs. an in progress compilation), - // it's possible that the target project has been removed. - if (referencedProject != null) + // The final state we produce will be frozen or not depending on if a frozen state was passed into it. + var isFrozen = allSyntaxTreesParsedState.IsFrozen; + var generatorInfo = allSyntaxTreesParsedState.GeneratorInfo; + var compilationWithoutGeneratedDocuments = allSyntaxTreesParsedState.CompilationWithoutGeneratedDocuments; + var staleCompilationWithGeneratedDocuments = allSyntaxTreesParsedState.StaleCompilationWithGeneratedDocuments; + + // Project is complete only if the following are all true: + // 1. HasAllInformation flag is set for the project + // 2. Either the project has non-zero metadata references OR this is the corlib project. + // For the latter, we use a heuristic if the underlying compilation defines "System.Object" type. + var hasSuccessfullyLoaded = this.ProjectState.HasAllInformation && + (this.ProjectState.MetadataReferences.Count > 0 || + compilationWithoutGeneratedDocuments.GetTypeByMetadataName("System.Object") != null); + + var newReferences = new List(); + var metadataReferenceToProjectId = new Dictionary(); + newReferences.AddRange(this.ProjectState.MetadataReferences); + + foreach (var projectReference in this.ProjectState.ProjectReferences) { - // If both projects are submissions, we'll count this as a previous submission link - // instead of a regular metadata reference - if (referencedProject.IsSubmission) - { - // if the referenced project is a submission project must be a submission as well: - Debug.Assert(this.ProjectState.IsSubmission); - - // We now need to (potentially) update the prior submission compilation. That Compilation is held in the - // ScriptCompilationInfo that we need to replace as a unit. - var previousSubmissionCompilation = - await compilationState.GetCompilationAsync( - projectReference.ProjectId, cancellationToken).ConfigureAwait(false); - - if (compilationWithoutGeneratedFiles.ScriptCompilationInfo!.PreviousScriptCompilation != previousSubmissionCompilation) - { - compilationWithoutGeneratedFiles = compilationWithoutGeneratedFiles.WithScriptCompilationInfo( - compilationWithoutGeneratedFiles.ScriptCompilationInfo!.WithPreviousScriptCompilation(previousSubmissionCompilation!)); + var referencedProject = compilationState.SolutionState.GetProjectState(projectReference.ProjectId); - compilationWithStaleGeneratedTrees = compilationWithStaleGeneratedTrees?.WithScriptCompilationInfo( - compilationWithStaleGeneratedTrees.ScriptCompilationInfo!.WithPreviousScriptCompilation(previousSubmissionCompilation!)); - } - } - else + // Even though we're creating a final compilation (vs. an in progress compilation), + // it's possible that the target project has been removed. + if (referencedProject != null) { - var metadataReference = await compilationState.GetMetadataReferenceAsync( - projectReference, this.ProjectState, cancellationToken).ConfigureAwait(false); - - // A reference can fail to be created if a skeleton assembly could not be constructed. - if (metadataReference != null) + // If both projects are submissions, we'll count this as a previous submission link + // instead of a regular metadata reference + if (referencedProject.IsSubmission) { - newReferences.Add(metadataReference); - metadataReferenceToProjectId.Add(metadataReference, projectReference.ProjectId); + // if the referenced project is a submission project must be a submission as well: + Debug.Assert(this.ProjectState.IsSubmission); + + // We now need to (potentially) update the prior submission compilation. That Compilation is held in the + // ScriptCompilationInfo that we need to replace as a unit. + var previousSubmissionCompilation = + await compilationState.GetCompilationAsync( + projectReference.ProjectId, cancellationToken).ConfigureAwait(false); + + if (compilationWithoutGeneratedDocuments.ScriptCompilationInfo!.PreviousScriptCompilation != previousSubmissionCompilation) + { + compilationWithoutGeneratedDocuments = compilationWithoutGeneratedDocuments.WithScriptCompilationInfo( + compilationWithoutGeneratedDocuments.ScriptCompilationInfo!.WithPreviousScriptCompilation(previousSubmissionCompilation!)); + + staleCompilationWithGeneratedDocuments = staleCompilationWithGeneratedDocuments?.WithScriptCompilationInfo( + staleCompilationWithGeneratedDocuments.ScriptCompilationInfo!.WithPreviousScriptCompilation(previousSubmissionCompilation!)); + } } else { - hasSuccessfullyLoaded = false; + var metadataReference = await compilationState.GetMetadataReferenceAsync( + projectReference, this.ProjectState, cancellationToken).ConfigureAwait(false); + + // A reference can fail to be created if a skeleton assembly could not be constructed. + if (metadataReference != null) + { + newReferences.Add(metadataReference); + metadataReferenceToProjectId.Add(metadataReference, projectReference.ProjectId); + } + else + { + hasSuccessfullyLoaded = false; + } } } } - } - // Now that we know the set of references this compilation should have, update them if they're not already. - // Generators cannot add references, so we can use the same set of references both for the compilation - // that doesn't have generated files, and the one we're trying to reuse that has generated files. - // Since we updated both of these compilations together in response to edits, we only have to check one - // for a potential mismatch. - if (!Enumerable.SequenceEqual(compilationWithoutGeneratedFiles.ExternalReferences, newReferences)) + // Now that we know the set of references this compilation should have, update them if they're not already. + // Generators cannot add references, so we can use the same set of references both for the compilation + // that doesn't have generated files, and the one we're trying to reuse that has generated files. + // Since we updated both of these compilations together in response to edits, we only have to check one + // for a potential mismatch. + if (!Enumerable.SequenceEqual(compilationWithoutGeneratedDocuments.ExternalReferences, newReferences)) + { + compilationWithoutGeneratedDocuments = compilationWithoutGeneratedDocuments.WithReferences(newReferences); + staleCompilationWithGeneratedDocuments = staleCompilationWithGeneratedDocuments?.WithReferences(newReferences); + } + + // We will finalize the compilation by adding full contents here. + var (compilationWithGeneratedDocuments, generatedDocuments, generatorDriver) = await AddExistingOrComputeNewGeneratorInfoAsync( + compilationState, + compilationWithoutGeneratedDocuments, + generatorInfo, + staleCompilationWithGeneratedDocuments, + cancellationToken).ConfigureAwait(false); + + // After producing the sg documents, we must always be in the final state for the generator data. + var nextGeneratorInfo = new CompilationTrackerGeneratorInfo(generatedDocuments, generatorDriver, DocumentsAreFinal: true); + + var finalState = FinalCompilationTrackerState.Create( + isFrozen, + compilationWithGeneratedDocuments, + compilationWithoutGeneratedDocuments, + hasSuccessfullyLoaded, + nextGeneratorInfo, + this.ProjectState.Id, + metadataReferenceToProjectId); + + this.WriteState(finalState); + + return finalState; + } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { - compilationWithoutGeneratedFiles = compilationWithoutGeneratedFiles.WithReferences(newReferences); - compilationWithStaleGeneratedTrees = compilationWithStaleGeneratedTrees?.WithReferences(newReferences); + // Explicitly force a yield point here. This addresses a problem on .net framework where it's + // possible that cancelling this task chain ends up stack overflowing as the TPL attempts to + // synchronously recurse through the tasks to execute antecedent work. This will force continuations + // here to run asynchronously preventing the stack overflow. + // See https://github.com/dotnet/roslyn/issues/56356 for more details. + // note: this can be removed if this code only needs to run on .net core (as the stack overflow issue + // does not exist there). + await Task.Yield().ConfigureAwait(false); + throw; + } + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) + { + throw ExceptionUtilities.Unreachable(); } - - // We will finalize the compilation by adding full contents here. - var (compilationWithGeneratedFiles, nextGeneratorInfo) = await AddExistingOrComputeNewGeneratorInfoAsync( - compilationState, - compilationWithoutGeneratedFiles, - generatorInfo, - compilationWithStaleGeneratedTrees, - cancellationToken).ConfigureAwait(false); - - var finalState = FinalState.Create( - compilationWithGeneratedFiles, - compilationWithoutGeneratedFiles, - hasSuccessfullyLoaded, - nextGeneratorInfo, - compilationWithGeneratedFiles, - this.ProjectState.Id, - metadataReferenceToProjectId); - - this.WriteState(finalState); - - return new CompilationInfo(compilationWithGeneratedFiles, hasSuccessfullyLoaded, nextGeneratorInfo); } - catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + } + + private Compilation CreateEmptyCompilation() + { + var compilationFactory = this.ProjectState.LanguageServices.GetRequiredService(); + + if (this.ProjectState.IsSubmission) { - // Explicitly force a yield point here. This addresses a problem on .net framework where it's - // possible that cancelling this task chain ends up stack overflowing as the TPL attempts to - // synchronously recurse through the tasks to execute antecedent work. This will force continuations - // here to run asynchronously preventing the stack overflow. - // See https://github.com/dotnet/roslyn/issues/56356 for more details. - // note: this can be removed if this code only needs to run on .net core (as the stack overflow issue - // does not exist there). - await Task.Yield().ConfigureAwait(false); - throw; + return compilationFactory.CreateSubmissionCompilation( + this.ProjectState.AssemblyName, + this.ProjectState.CompilationOptions!, + this.ProjectState.HostObjectType); } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) + else { - throw ExceptionUtilities.Unreachable(); + return compilationFactory.CreateCompilation( + this.ProjectState.AssemblyName, + this.ProjectState.CompilationOptions!); } } @@ -832,14 +801,12 @@ await compilationState.GetCompilationAsync( /// public MetadataReference? GetPartialMetadataReference(ProjectState fromProject, ProjectReference projectReference) { - var state = ReadState(); - if (ProjectState.LanguageServices == fromProject.LanguageServices) { // if we have a compilation and its the correct language, use a simple compilation reference in any // state it happens to be in right now - if (state.CompilationWithoutGeneratedDocuments is { } compilation) - return compilation.ToMetadataReference(projectReference.Aliases, projectReference.EmbedInteropTypes); + if (ReadState() is CompilationTrackerState compilationState) + return compilationState.CompilationWithoutGeneratedDocuments.ToMetadataReference(projectReference.Aliases, projectReference.EmbedInteropTypes); } else { @@ -856,24 +823,17 @@ await compilationState.GetCompilationAsync( public Task HasSuccessfullyLoadedAsync( SolutionCompilationState compilationState, CancellationToken cancellationToken) { - var state = this.ReadState(); - - if (state.HasSuccessfullyLoaded.HasValue) - { - return state.HasSuccessfullyLoaded.Value ? SpecializedTasks.True : SpecializedTasks.False; - } - else - { - return HasSuccessfullyLoadedSlowAsync(compilationState, cancellationToken); - } + return this.ReadState() is FinalCompilationTrackerState finalState + ? finalState.HasSuccessfullyLoaded ? SpecializedTasks.True : SpecializedTasks.False + : HasSuccessfullyLoadedSlowAsync(compilationState, cancellationToken); } private async Task HasSuccessfullyLoadedSlowAsync( SolutionCompilationState compilationState, CancellationToken cancellationToken) { - var compilationInfo = await GetOrBuildCompilationInfoAsync( - compilationState, lockGate: true, cancellationToken: cancellationToken).ConfigureAwait(false); - return compilationInfo.HasSuccessfullyLoaded; + var finalState = await GetOrBuildFinalStateAsync( + compilationState, cancellationToken: cancellationToken).ConfigureAwait(false); + return finalState.HasSuccessfullyLoaded; } public async ValueTask> GetSourceGeneratedDocumentStatesAsync( @@ -885,9 +845,9 @@ public async ValueTask> GetSour return TextDocumentStates.Empty; } - var compilationInfo = await GetOrBuildCompilationInfoAsync( - compilationState, lockGate: true, cancellationToken: cancellationToken).ConfigureAwait(false); - return compilationInfo.GeneratorInfo.Documents; + var finalState = await GetOrBuildFinalStateAsync( + compilationState, cancellationToken: cancellationToken).ConfigureAwait(false); + return finalState.GeneratorInfo.Documents; } public async ValueTask> GetSourceGeneratorDiagnosticsAsync( @@ -898,10 +858,10 @@ public async ValueTask> GetSourceGeneratorDiagnostics return []; } - var compilationInfo = await GetOrBuildCompilationInfoAsync( - compilationState, lockGate: true, cancellationToken: cancellationToken).ConfigureAwait(false); + var finalState = await GetOrBuildFinalStateAsync( + compilationState, cancellationToken: cancellationToken).ConfigureAwait(false); - var driverRunResult = compilationInfo.GeneratorInfo.Driver?.GetRunResult(); + var driverRunResult = finalState.GeneratorInfo.Driver?.GetRunResult(); if (driverRunResult is null) { return []; @@ -927,7 +887,7 @@ public async ValueTask> GetSourceGeneratorDiagnostics // If we are in FinalState, then we have correctly ran generators and then know the final contents of the // Compilation. The GeneratedDocuments can be filled for intermediate states, but those aren't guaranteed to be // correct and can be re-ran later. - return state is FinalState finalState ? finalState.GeneratorInfo.Documents.GetState(documentId) : null; + return state is FinalCompilationTrackerState finalState ? finalState.GeneratorInfo.Documents.GetState(documentId) : null; } // HACK HACK HACK HACK around a problem introduced by https://github.com/dotnet/sdk/pull/24928. The Razor generator is @@ -963,22 +923,25 @@ private bool IsGeneratorRunResultToIgnore(GeneratorRunResult result) /// /// Validates the compilation is consistent and we didn't have a bug in producing it. This only runs under a feature flag. /// - private void ValidateState(CompilationTrackerState state) + private void ValidateState(CompilationTrackerState? state) { + if (state is null) + return; + if (!_validateStates) return; - if (state is FinalState finalState) + if (state is FinalCompilationTrackerState finalState) { - ValidateCompilationTreesMatchesProjectState(finalState.FinalCompilationWithGeneratedDocuments, ProjectState, state.GeneratorInfo); + ValidateCompilationTreesMatchesProjectState(finalState.FinalCompilationWithGeneratedDocuments, ProjectState, finalState.GeneratorInfo); } else if (state is InProgressState inProgressState) { - ValidateCompilationTreesMatchesProjectState(inProgressState.CompilationWithoutGeneratedDocuments!, inProgressState.IntermediateProjects[0].oldState, generatorInfo: null); + ValidateCompilationTreesMatchesProjectState(inProgressState.CompilationWithoutGeneratedDocuments, inProgressState.IntermediateProjects[0].oldState, generatorInfo: null); - if (inProgressState.CompilationWithGeneratedDocuments != null) + if (inProgressState.StaleCompilationWithGeneratedDocuments != null) { - ValidateCompilationTreesMatchesProjectState(inProgressState.CompilationWithGeneratedDocuments, inProgressState.IntermediateProjects[0].oldState, inProgressState.GeneratorInfo); + ValidateCompilationTreesMatchesProjectState(inProgressState.StaleCompilationWithGeneratedDocuments, inProgressState.IntermediateProjects[0].oldState, inProgressState.GeneratorInfo); } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTrackerGeneratorInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTrackerGeneratorInfo.cs new file mode 100644 index 0000000000000..f76176dc269e2 --- /dev/null +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTrackerGeneratorInfo.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. + +namespace Microsoft.CodeAnalysis; + +internal partial class SolutionCompilationState +{ + private partial class CompilationTracker + { + /// + /// The best generated documents we have for the current state. specifies + /// whether the documents are to be considered final and can be reused, or whether they're from a prior snapshot + /// which needs to be recomputed. + /// + /// + /// The that was used for the last run, to allow for incremental reuse. May be + /// null if we don't have generators in the first place, haven't ran generators yet for this project, or had to + /// get rid of our driver for some reason. + /// + /// + /// Whether the generated documents in are final and should not be regenerated. + /// It's important that once we've ran generators once we don't want to run them again. Once we've ran + /// them the first time, those syntax trees are visible from other parts of the Workspaces model; if we + /// run them a second time we'd end up with new trees which would confuse our snapshot model -- once the + /// tree has been handed out we can't make a second tree later. + /// + private readonly record struct CompilationTrackerGeneratorInfo( + TextDocumentStates Documents, + GeneratorDriver? Driver, + bool DocumentsAreFinal) + { + public static readonly CompilationTrackerGeneratorInfo Empty = + new(TextDocumentStates.Empty, driver: null); + + public CompilationTrackerGeneratorInfo( + TextDocumentStates documents, + GeneratorDriver? driver) : this(documents, driver, DocumentsAreFinal: false) + { + } + } + } +} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker_Generators.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker_Generators.cs index 2c778ab5bb386..fd0535248c5f0 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker_Generators.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.CompilationTracker_Generators.cs @@ -26,7 +26,7 @@ internal partial class SolutionCompilationState { private partial class CompilationTracker : ICompilationTracker { - private async Task<(Compilation compilationWithGeneratedFiles, CompilationTrackerGeneratorInfo generatorInfo)> AddExistingOrComputeNewGeneratorInfoAsync( + private async Task<(Compilation compilationWithGeneratedFiles, TextDocumentStates generatedDocuments, GeneratorDriver? generatorDriver)> AddExistingOrComputeNewGeneratorInfoAsync( SolutionCompilationState compilationState, Compilation compilationWithoutGeneratedFiles, CompilationTrackerGeneratorInfo generatorInfo, @@ -45,29 +45,30 @@ await generatorInfo.Documents.States.Values.SelectAsArrayAsync( static (state, cancellationToken) => state.GetSyntaxTreeAsync(cancellationToken), cancellationToken).ConfigureAwait(false)); // Will reuse the generator info since we're reusing all the trees from within it. - return (compilationWithGeneratedFiles, generatorInfo); + return (compilationWithGeneratedFiles, generatorInfo.Documents, generatorInfo.Driver); } if (!this.ProjectState.SourceGenerators.Any()) { // We don't have any source generators. Trivially bail out. var compilationWithGeneratedFiles = compilationWithoutGeneratedFiles; - return (compilationWithGeneratedFiles, new CompilationTrackerGeneratorInfo( - TextDocumentStates.Empty, generatorInfo.Driver, documentsAreFinal: true)); + return (compilationWithGeneratedFiles, TextDocumentStates.Empty, generatorInfo.Driver); } return await ComputeNewGeneratorInfoAsync( compilationState, compilationWithoutGeneratedFiles, - generatorInfo, + generatorInfo.Documents, + generatorInfo.Driver, compilationWithStaleGeneratedTrees, cancellationToken).ConfigureAwait(false); } - private async Task<(Compilation compilationWithGeneratedFiles, CompilationTrackerGeneratorInfo generatorInfo)> ComputeNewGeneratorInfoAsync( + private async Task<(Compilation compilationWithGeneratedFiles, TextDocumentStates generatedDocuments, GeneratorDriver? generatorDriver)> ComputeNewGeneratorInfoAsync( SolutionCompilationState compilationState, Compilation compilationWithoutGeneratedFiles, - CompilationTrackerGeneratorInfo generatorInfo, + TextDocumentStates oldGeneratedDocuments, + GeneratorDriver? oldGeneratorDriver, Compilation? compilationWithStaleGeneratedTrees, CancellationToken cancellationToken) { @@ -75,20 +76,29 @@ await generatorInfo.Documents.States.Values.SelectAsArrayAsync( // back over to us to ensure that both processes are in total agreement about the SG docs and their // contents. var result = await TryComputeNewGeneratorInfoInRemoteProcessAsync( - compilationState, compilationWithoutGeneratedFiles, generatorInfo, compilationWithStaleGeneratedTrees, cancellationToken).ConfigureAwait(false); + compilationState, compilationWithoutGeneratedFiles, oldGeneratedDocuments, compilationWithStaleGeneratedTrees, cancellationToken).ConfigureAwait(false); if (result.HasValue) - return result.Value; + { + // Since we ran the SG work out of process, we could not have created or modified the driver passed in. + // So just pass what we got in right back out. + return (result.Value.compilationWithGeneratedFiles, result.Value.generatedDocuments, oldGeneratorDriver); + } // If that failed (OOP crash, or we are the OOP process ourselves), then generate the SG docs locally. var telemetryCollector = compilationState.SolutionState.Services.GetService(); return await ComputeNewGeneratorInfoInCurrentProcessAsync( - telemetryCollector, compilationWithoutGeneratedFiles, generatorInfo, compilationWithStaleGeneratedTrees, cancellationToken).ConfigureAwait(false); + telemetryCollector, + compilationWithoutGeneratedFiles, + oldGeneratedDocuments, + oldGeneratorDriver, + compilationWithStaleGeneratedTrees, + cancellationToken).ConfigureAwait(false); } - private async Task<(Compilation compilationWithGeneratedFiles, CompilationTrackerGeneratorInfo generatorInfo)?> TryComputeNewGeneratorInfoInRemoteProcessAsync( + private async Task<(Compilation compilationWithGeneratedFiles, TextDocumentStates generatedDocuments)?> TryComputeNewGeneratorInfoInRemoteProcessAsync( SolutionCompilationState compilationState, Compilation compilationWithoutGeneratedFiles, - CompilationTrackerGeneratorInfo generatorInfo, + TextDocumentStates oldGeneratedDocuments, Compilation? compilationWithStaleGeneratedTrees, CancellationToken cancellationToken) { @@ -129,7 +139,7 @@ await generatorInfo.Documents.States.Values.SelectAsArrayAsync( var documentId = documentIdentity.DocumentId; Contract.ThrowIfFalse(documentId.IsSourceGenerated); - var existingDocument = generatorInfo.Documents.GetState(documentId); + var existingDocument = oldGeneratedDocuments.GetState(documentId); // Can keep what we have if it has the same doc and content identity. if (existingDocument?.Identity == documentIdentity && @@ -145,12 +155,12 @@ await generatorInfo.Documents.States.Values.SelectAsArrayAsync( // If we produced just as many documents as before, and none of them required any changes, then we can // reuse the prior compilation. - if (infos.Length == generatorInfo.Documents.Count && + if (infos.Length == oldGeneratedDocuments.Count && documentsToAddOrUpdate.Count == 0 && compilationWithStaleGeneratedTrees != null && - generatorInfo.Documents.States.All(kvp => kvp.Value.ParseOptions.Equals(this.ProjectState.ParseOptions))) + oldGeneratedDocuments.States.All(kvp => kvp.Value.ParseOptions.Equals(this.ProjectState.ParseOptions))) { - return (compilationWithStaleGeneratedTrees, generatorInfo.WithDocumentsAreFinal(true)); + return (compilationWithStaleGeneratedTrees, oldGeneratedDocuments); } // Either we generated a different number of files, and/or we had contents of files that changed. Ensure @@ -197,7 +207,7 @@ await generatorInfo.Documents.States.Values.SelectAsArrayAsync( else { // a document that already matched something locally. - var existingDocument = generatorInfo.Documents.GetRequiredState(documentId); + var existingDocument = oldGeneratedDocuments.GetRequiredState(documentId); Contract.ThrowIfTrue(existingDocument.Identity != documentIdentity, "Identities must match!"); Contract.ThrowIfTrue(existingDocument.GetOriginalSourceTextContentHash() != contentIdentity.OriginalSourceTextContentHash, "Checksums must match!"); @@ -207,51 +217,52 @@ await generatorInfo.Documents.States.Values.SelectAsArrayAsync( } } - var generatedDocuments = new TextDocumentStates(generatedDocumentsBuilder.ToImmutableAndClear()); + var newGeneratedDocuments = new TextDocumentStates(generatedDocumentsBuilder.ToImmutableAndClear()); var compilationWithGeneratedFiles = compilationWithoutGeneratedFiles.AddSyntaxTrees( - await generatedDocuments.States.Values.SelectAsArrayAsync( + await newGeneratedDocuments.States.Values.SelectAsArrayAsync( static (state, cancellationToken) => state.GetSyntaxTreeAsync(cancellationToken), cancellationToken).ConfigureAwait(false)); - return (compilationWithGeneratedFiles, new CompilationTrackerGeneratorInfo(generatedDocuments, generatorInfo.Driver, documentsAreFinal: true)); + return (compilationWithGeneratedFiles, newGeneratedDocuments); } - private async Task<(Compilation compilationWithGeneratedFiles, CompilationTrackerGeneratorInfo generatorInfo)> ComputeNewGeneratorInfoInCurrentProcessAsync( + private async Task<(Compilation compilationWithGeneratedFiles, TextDocumentStates generatedDocuments, GeneratorDriver? generatorDriver)> ComputeNewGeneratorInfoInCurrentProcessAsync( ISourceGeneratorTelemetryCollectorWorkspaceService? telemetryCollector, Compilation compilationWithoutGeneratedFiles, - CompilationTrackerGeneratorInfo generatorInfo, + TextDocumentStates oldGeneratedDocuments, + GeneratorDriver? generatorDriver, Compilation? compilationWithStaleGeneratedTrees, CancellationToken cancellationToken) { // We have at least one source generator. If we don't already have a generator driver, we'll have to // create one from scratch - if (generatorInfo.Driver == null) + if (generatorDriver == null) { var additionalTexts = this.ProjectState.AdditionalDocumentStates.SelectAsArray(static documentState => documentState.AdditionalText); var compilationFactory = this.ProjectState.LanguageServices.GetRequiredService(); - generatorInfo = generatorInfo.WithDriver(compilationFactory.CreateGeneratorDriver( + generatorDriver = compilationFactory.CreateGeneratorDriver( this.ProjectState.ParseOptions!, ProjectState.SourceGenerators.ToImmutableArray(), this.ProjectState.AnalyzerOptions.AnalyzerConfigOptionsProvider, - additionalTexts)); + additionalTexts); } else { #if DEBUG // Assert that the generator driver is in sync with our additional document states; there's not a public // API to get this, but we'll reflect in DEBUG-only. - var driverType = generatorInfo.Driver.GetType(); + var driverType = generatorDriver.GetType(); var stateMember = driverType.GetField("_state", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); Contract.ThrowIfNull(stateMember); var additionalTextsMember = stateMember.FieldType.GetField("AdditionalTexts", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); Contract.ThrowIfNull(additionalTextsMember); - var state = stateMember.GetValue(generatorInfo.Driver); + var state = stateMember.GetValue(generatorDriver); var additionalTexts = (ImmutableArray)additionalTextsMember.GetValue(state)!; Contract.ThrowIfFalse(additionalTexts.Length == this.ProjectState.AdditionalDocumentStates.Count); #endif } - Contract.ThrowIfNull(generatorInfo.Driver); + Contract.ThrowIfNull(generatorDriver); // HACK HACK HACK HACK to address https://github.com/dotnet/roslyn/issues/59818. There, we were running into issues where // a generator being present and consuming syntax was causing all red nodes to be processed. This was problematic when @@ -272,12 +283,13 @@ await generatedDocuments.States.Values.SelectAsArrayAsync( var compilationToRunGeneratorsOn = compilationWithoutGeneratedFiles.RemoveSyntaxTrees(treesToRemove); // END HACK HACK HACK HACK. - generatorInfo = generatorInfo.WithDriver(generatorInfo.Driver.RunGenerators(compilationToRunGeneratorsOn, cancellationToken)); - Contract.ThrowIfNull(generatorInfo.Driver); + generatorDriver = generatorDriver.RunGenerators(compilationToRunGeneratorsOn, cancellationToken); + + Contract.ThrowIfNull(generatorDriver); - var runResult = generatorInfo.Driver.GetRunResult(); + var runResult = generatorDriver.GetRunResult(); - telemetryCollector?.CollectRunResult(runResult, generatorInfo.Driver.GetTimingInfo(), ProjectState); + telemetryCollector?.CollectRunResult(runResult, generatorDriver.GetTimingInfo(), ProjectState); // We may be able to reuse compilationWithStaleGeneratedTrees if the generated trees are identical. We will assign null // to compilationWithStaleGeneratedTrees if we at any point realize it can't be used. We'll first check the count of trees @@ -289,7 +301,7 @@ await generatedDocuments.States.Values.SelectAsArrayAsync( var generatedTreeCount = runResult.Results.Sum(r => IsGeneratorRunResultToIgnore(r) ? 0 : r.GeneratedSources.Length); - if (generatorInfo.Documents.Count != generatedTreeCount) + if (oldGeneratedDocuments.Count != generatedTreeCount) compilationWithStaleGeneratedTrees = null; } @@ -304,7 +316,7 @@ await generatedDocuments.States.Values.SelectAsArrayAsync( foreach (var generatedSource in generatorResult.GeneratedSources) { var existing = FindExistingGeneratedDocumentState( - generatorInfo.Documents, + oldGeneratedDocuments, generatorResult.Generator, generatorAnalyzerReference, generatedSource.HintName); @@ -350,14 +362,14 @@ await generatedDocuments.States.Values.SelectAsArrayAsync( // If we didn't null out this compilation, it means we can actually use it if (compilationWithStaleGeneratedTrees != null) - return (compilationWithStaleGeneratedTrees, generatorInfo.WithDocumentsAreFinal(true)); + return (compilationWithStaleGeneratedTrees, oldGeneratedDocuments, generatorDriver); // We produced new documents, so time to create new state for it - var generatedDocuments = new TextDocumentStates(generatedDocumentsBuilder.ToImmutableAndClear()); + var newGeneratedDocuments = new TextDocumentStates(generatedDocumentsBuilder.ToImmutableAndClear()); var compilationWithGeneratedFiles = compilationWithoutGeneratedFiles.AddSyntaxTrees( - await generatedDocuments.States.Values.SelectAsArrayAsync( + await newGeneratedDocuments.States.Values.SelectAsArrayAsync( static (state, cancellationToken) => state.GetSyntaxTreeAsync(cancellationToken), cancellationToken).ConfigureAwait(false)); - return (compilationWithGeneratedFiles, new CompilationTrackerGeneratorInfo(generatedDocuments, generatorInfo.Driver, documentsAreFinal: true)); + return (compilationWithGeneratedFiles, newGeneratedDocuments, generatorDriver); static SourceGeneratedDocumentState? FindExistingGeneratedDocumentState( TextDocumentStates states, diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.cs index c543897985aed..56f23ba006882 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState.cs @@ -15,7 +15,6 @@ using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.Logging; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; @@ -59,9 +58,10 @@ internal sealed partial class SolutionCompilationState private NonReentrantLock? _stateLockBackingField; private NonReentrantLock StateLock => LazyInitializer.EnsureInitialized(ref _stateLockBackingField, NonReentrantLock.Factory); - private WeakReference? _latestSolutionWithPartialCompilation; - private DateTime _timeOfLatestSolutionWithPartialCompilation; - private DocumentId? _documentIdOfLatestSolutionWithPartialCompilation; + /// + /// Mapping of DocumentId to the frozen compilation state we produced for it the last time we were queried. + /// + private readonly Dictionary _cachedFrozenDocumentState = new(); private SolutionCompilationState( SolutionState solution, @@ -602,10 +602,10 @@ public SolutionCompilationState WithDocumentSyntaxRoot( } public SolutionCompilationState WithDocumentContentsFrom( - DocumentId documentId, DocumentState documentState) + DocumentId documentId, DocumentState documentState, bool forceEvenIfTreesWouldDiffer) { return UpdateDocumentState( - this.SolutionState.WithDocumentContentsFrom(documentId, documentState), documentId); + this.SolutionState.WithDocumentContentsFrom(documentId, documentState, forceEvenIfTreesWouldDiffer), documentId); } /// @@ -1017,70 +1017,113 @@ public SolutionCompilationState WithOptions(SolutionOptionSet options) public SolutionCompilationState WithFrozenPartialCompilationIncludingSpecificDocument( DocumentId documentId, CancellationToken cancellationToken) { - try - { - var allDocumentIds = this.SolutionState.GetRelatedDocumentIds(documentId); - using var _ = ArrayBuilder<(DocumentState, SyntaxTree)>.GetInstance(allDocumentIds.Length, out var builder); - - foreach (var currentDocumentId in allDocumentIds) - { - var document = this.SolutionState.GetRequiredDocumentState(currentDocumentId); - builder.Add((document, document.GetSyntaxTree(cancellationToken))); - } + // in progress solutions are disabled for some testing + if (this.Services.GetService()?.IsPartialSolutionDisabled == true) + return this; - using (this.StateLock.DisposableWait(cancellationToken)) + var currentCompilationState = this; + var currentDocumentState = this.SolutionState.GetRequiredDocumentState(documentId); + + // We want all linked versions of this document to also be present in the frozen solution snapshot (that way + // features like 'completion' can see that there are linked docs and give messages about symbols not being + // available in certain project contexts). We do this in a slightly hacky way for perf though. Specifically, + // instead of parsing *all* the sibling files (which can be expensive, especially for a file linked in many + // projects/tfms), we only parse this single tree. We then use that same tree across all siblings. That's + // technically inaccurate, but we can accept that as the primary purpose of 'frozen partial' is to get a + // snapshot *fast* that is allowed to be *inaccurate*. + // + // Note: this does mean that some *potentially* desirable feature behaviors may not be possible. For example, + // because of this unification, all targets will see the user in the same parsed #if region. That means, if the + // user is in a conditionally-disabled region in the primary target, they will also be in such a region in all + // other targets. This would prevent such a feature from using the information from other targets (perhaps + // where it is not conditionally-disabled) to drive a richer experience here. We consider that acceptable given + // the perf benefit. But we could consider relaxing this in the future. + // + // Note: this is very different from the logic we have in the workspace to 'UnifyLinkedDocumentContents'. In + // that case, we only share trees when completely safe and accurate to do so (for example, where no + // directives are involved). As that is used for the real solution snapshot, it must be correct. The + // frozen-partial snapshot is different as it is a fork that is already allowed to be inaccurate for perf + // reasons (for example, missing trees, or missing references). + // + // The 'forceEvenIfTreesWouldDiffer' flag here allows us to share the doc contents even in the case where + // correctness might be violated. + // + // Note: this forking can still be expensive. It would be nice to do this as one large fork step rather than N + // medium sized ones. + // + // Note: GetRelatedDocumentIds will include `documentId` as well. But that's ok. Calling + // WithDocumentContentsFrom with the current document state no-ops immediately, returning back the same + // compilation state instance. So in the case where there are no linked documents, there is no cost here. And + // there is no additional cost processing the initiating document in this loop. + var allDocumentIds = this.SolutionState.GetRelatedDocumentIds(documentId); + foreach (var siblingId in allDocumentIds) + currentCompilationState = currentCompilationState.WithDocumentContentsFrom(siblingId, currentDocumentState, forceEvenIfTreesWouldDiffer: true); + + return WithFrozenPartialCompilationIncludingSpecificDocumentWorker(currentCompilationState, documentId, cancellationToken); + + // Intentionally static, so we only operate on @this, not `this`. + static SolutionCompilationState WithFrozenPartialCompilationIncludingSpecificDocumentWorker( + SolutionCompilationState @this, DocumentId documentId, CancellationToken cancellationToken) + { + try { - // in progress solutions are disabled for some testing - if (Services.GetService()?.IsPartialSolutionDisabled == true) + var allDocumentIds = @this.SolutionState.GetRelatedDocumentIds(documentId); + using var _ = ArrayBuilder<(DocumentState, SyntaxTree)>.GetInstance(allDocumentIds.Length, out var statesAndTrees); + + // We grab all the contents of linked files as well to ensure that our snapshot is correct wrt to the + // set of linked document ids our state says are in it. Note: all of these trees should share the same + // green trees, as that is setup in our outer caller. This helps ensure that the cost here is low for + // files with lots of linked siblings. + foreach (var currentDocumentId in allDocumentIds) { - return this; + var documentState = @this.SolutionState.GetRequiredDocumentState(currentDocumentId); + statesAndTrees.Add((documentState, documentState.GetSyntaxTree(cancellationToken))); } - SolutionCompilationState? currentPartialSolution = null; - _latestSolutionWithPartialCompilation?.TryGetTarget(out currentPartialSolution); - - var reuseExistingPartialSolution = - (DateTime.UtcNow - _timeOfLatestSolutionWithPartialCompilation).TotalSeconds < 0.1 && - _documentIdOfLatestSolutionWithPartialCompilation == documentId; - - if (reuseExistingPartialSolution && currentPartialSolution != null) + using (@this.StateLock.DisposableWait(cancellationToken)) { - SolutionLogger.UseExistingPartialSolution(); - return currentPartialSolution; - } - - var newIdToProjectStateMap = this.SolutionState.ProjectStates; - var newIdToTrackerMap = _projectIdToTrackerMap; + if (!@this._cachedFrozenDocumentState.TryGetValue(documentId, out var compilationState)) + { + compilationState = ComputeFrozenPartialState(@this, statesAndTrees, cancellationToken); + @this._cachedFrozenDocumentState.Add(documentId, compilationState); + } - foreach (var (doc, tree) in builder) - { - // if we don't have one or it is stale, create a new partial solution - var tracker = this.GetCompilationTracker(doc.Id.ProjectId); - var newTracker = tracker.FreezePartialStateWithTree(this, doc, tree, cancellationToken); - - Contract.ThrowIfFalse(newIdToProjectStateMap.ContainsKey(doc.Id.ProjectId)); - newIdToProjectStateMap = newIdToProjectStateMap.SetItem(doc.Id.ProjectId, newTracker.ProjectState); - newIdToTrackerMap = newIdToTrackerMap.SetItem(doc.Id.ProjectId, newTracker); + return compilationState; } + } + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) + { + throw ExceptionUtilities.Unreachable(); + } + } - var newState = this.SolutionState.Branch( - idToProjectStateMap: newIdToProjectStateMap, - dependencyGraph: SolutionState.CreateDependencyGraph(this.SolutionState.ProjectIds, newIdToProjectStateMap)); - var newCompilationState = this.Branch( - newState, - newIdToTrackerMap); + static SolutionCompilationState ComputeFrozenPartialState( + SolutionCompilationState @this, + ArrayBuilder<(DocumentState, SyntaxTree)> statesAndTrees, + CancellationToken cancellationToken) + { + var newIdToProjectStateMap = @this.SolutionState.ProjectStates; + var newIdToTrackerMap = @this._projectIdToTrackerMap; - _latestSolutionWithPartialCompilation = new WeakReference(newCompilationState); - _timeOfLatestSolutionWithPartialCompilation = DateTime.UtcNow; - _documentIdOfLatestSolutionWithPartialCompilation = documentId; + foreach (var (docState, tree) in statesAndTrees) + { + // if we don't have one or it is stale, create a new partial solution + var tracker = @this.GetCompilationTracker(docState.Id.ProjectId); + var newTracker = tracker.FreezePartialStateWithTree(@this, docState, tree, cancellationToken); - SolutionLogger.CreatePartialSolution(); - return newCompilationState; + Contract.ThrowIfFalse(newIdToProjectStateMap.ContainsKey(docState.Id.ProjectId)); + newIdToProjectStateMap = newIdToProjectStateMap.SetItem(docState.Id.ProjectId, newTracker.ProjectState); + newIdToTrackerMap = newIdToTrackerMap.SetItem(docState.Id.ProjectId, newTracker); } - } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical)) - { - throw ExceptionUtilities.Unreachable(); + + var newState = @this.SolutionState.Branch( + idToProjectStateMap: newIdToProjectStateMap, + dependencyGraph: SolutionState.CreateDependencyGraph(@this.SolutionState.ProjectIds, newIdToProjectStateMap)); + var newCompilationState = @this.Branch( + newState, + newIdToTrackerMap); + + return newCompilationState; } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState_Checksum.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState_Checksum.cs index 4364aea4075a7..492b82685de5a 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState_Checksum.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionCompilationState_Checksum.cs @@ -4,16 +4,11 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.PooledObjects; -using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Serialization; using Roslyn.Utilities; @@ -128,175 +123,4 @@ private async Task ComputeChecksumsAsync( } } } - - internal partial class SolutionState - { - private static readonly ConditionalWeakTable, IReadOnlyList> s_projectIdToSortedProjectsMap = new(); - - /// - /// Checksum representing the full checksum tree for this solution compilation state. Includes the checksum for - /// . - /// - private readonly AsyncLazy _lazyChecksums; - - /// - /// Mapping from project-id to the checksums needed to synchronize it (and the projects it depends on) over - /// to an OOP host. Lock this specific field before reading/writing to it. - /// - private readonly Dictionary> _lazyProjectChecksums = new(); - - public static IReadOnlyList GetOrCreateSortedProjectIds(IReadOnlyList unorderedList) - => s_projectIdToSortedProjectsMap.GetValue(unorderedList, projectIds => projectIds.OrderBy(id => id.Id).ToImmutableArray()); - - public bool TryGetStateChecksums([NotNullWhen(true)] out SolutionStateChecksums? stateChecksums) - => _lazyChecksums.TryGetValue(out stateChecksums); - - public bool TryGetStateChecksums(ProjectId projectId, [NotNullWhen(true)] out SolutionStateChecksums? stateChecksums) - { - AsyncLazy? checksums; - lock (_lazyProjectChecksums) - { - if (!_lazyProjectChecksums.TryGetValue(projectId, out checksums) || - checksums == null) - { - stateChecksums = null; - return false; - } - } - - return checksums.TryGetValue(out stateChecksums); - } - - public Task GetStateChecksumsAsync(CancellationToken cancellationToken) - => _lazyChecksums.GetValueAsync(cancellationToken); - - public async Task GetChecksumAsync(CancellationToken cancellationToken) - { - var collection = await GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false); - return collection.Checksum; - } - - /// Gets the checksum for only the requested project (and any project it depends on) - public async Task GetStateChecksumsAsync( - ProjectId projectId, - CancellationToken cancellationToken) - { - Contract.ThrowIfNull(projectId); - - AsyncLazy? checksums; - lock (_lazyProjectChecksums) - { - if (!_lazyProjectChecksums.TryGetValue(projectId, out checksums)) - { - checksums = Compute(projectId); - _lazyProjectChecksums.Add(projectId, checksums); - } - } - - var collection = await checksums.GetValueAsync(cancellationToken).ConfigureAwait(false); - return collection; - - // Extracted as a local function to prevent delegate allocations when not needed. - AsyncLazy Compute(ProjectId projectId) - { - var projectsToInclude = new HashSet(); - AddReferencedProjects(projectsToInclude, projectId); - - return AsyncLazy.Create(c => ComputeChecksumsAsync(projectsToInclude, c)); - } - - void AddReferencedProjects(HashSet result, ProjectId projectId) - { - if (!result.Add(projectId)) - return; - - var projectState = this.GetProjectState(projectId); - if (projectState == null) - return; - - foreach (var refProject in projectState.ProjectReferences) - { - // Note: it's possible in the workspace to see project-ids that don't have a corresponding project - // state. While not desirable, we allow project's to have refs to projects that no longer exist - // anymore. This state is expected to be temporary until the project is explicitly told by the - // host to remove the reference. We do not expose this through the full Solution/Project which - // filters out this case already (in Project.ProjectReferences). However, becausde we're at the - // ProjectState level it cannot do that filtering unless examined through us (the SolutionState). - if (this.ProjectStates.ContainsKey(refProject.ProjectId)) - AddReferencedProjects(result, refProject.ProjectId); - } - } - } - - /// Gets the checksum for only the requested project (and any project it depends on) - public async Task GetChecksumAsync(ProjectId projectId, CancellationToken cancellationToken) - { - var checksums = await GetStateChecksumsAsync(projectId, cancellationToken).ConfigureAwait(false); - return checksums.Checksum; - } - - /// Cone of projects to compute a checksum for. Pass in - /// to get a checksum for the entire solution - private async Task ComputeChecksumsAsync( - HashSet? projectsToInclude, - CancellationToken cancellationToken) - { - try - { - using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, this.FilePath, cancellationToken)) - { - // get states by id order to have deterministic checksum. Limit expensive computation to the - // requested set of projects if applicable. - var orderedProjectIds = GetOrCreateSortedProjectIds(this.ProjectIds); - var projectChecksumTasks = orderedProjectIds - .Select(id => (state: this.ProjectStates[id], mustCompute: projectsToInclude == null || projectsToInclude.Contains(id))) - .Where(t => RemoteSupportedLanguages.IsSupported(t.state.Language)) - .Select(async t => - { - // if it's a project that's specifically in the sync'ed cone, include this checksum so that - // this project definitely syncs over. - if (t.mustCompute) - return await t.state.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false); - - // If it's a project that is not in the cone, still try to get the latest checksum for it if - // we have it. That way we don't send over a checksum *without* that project, causing the - // OOP side to throw that project away (along with all the compilation info stored with it). - if (t.state.TryGetStateChecksums(out var stateChecksums)) - return stateChecksums; - - // We have never computed the checksum for this project. Don't send anything for it. - return null; - }) - .ToArray(); - - var serializer = this.Services.GetRequiredService(); - var attributesChecksum = this.SolutionAttributes.Checksum; - - var analyzerReferenceChecksums = ChecksumCache.GetOrCreateChecksumCollection( - this.AnalyzerReferences, serializer, cancellationToken); - - var allResults = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false); - using var _1 = ArrayBuilder.GetInstance(allResults.Length, out var projectIds); - using var _2 = ArrayBuilder.GetInstance(allResults.Length, out var projectChecksums); - foreach (var projectStateChecksums in allResults) - { - if (projectStateChecksums != null) - { - projectIds.Add(projectStateChecksums.ProjectId); - projectChecksums.Add(projectStateChecksums.Checksum); - } - } - - return new SolutionStateChecksums( - attributesChecksum, - new(new ChecksumCollection(projectChecksums.ToImmutableAndClear()), projectIds.ToImmutableAndClear()), - analyzerReferenceChecksums); - } - } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) - { - throw ExceptionUtilities.Unreachable(); - } - } - } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs deleted file mode 100644 index 161afc1205301..0000000000000 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionLogger.cs +++ /dev/null @@ -1,42 +0,0 @@ -// 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 disable - -using Microsoft.CodeAnalysis.Internal.Log; - -namespace Microsoft.CodeAnalysis.Logging -{ - internal static class SolutionLogger - { - private static readonly CountLogAggregator s_logAggregator = new(); - - public static void UseExistingPartialProjectState() - => s_logAggregator.IncreaseCount(nameof(UseExistingPartialProjectState)); - - public static void UseExistingFullProjectState() - => s_logAggregator.IncreaseCount(nameof(UseExistingFullProjectState)); - - public static void CreatePartialProjectState() - => s_logAggregator.IncreaseCount(nameof(CreatePartialProjectState)); - - public static void UseExistingPartialSolution() - => s_logAggregator.IncreaseCount(nameof(UseExistingPartialSolution)); - - public static void CreatePartialSolution() - => s_logAggregator.IncreaseCount(nameof(CreatePartialSolution)); - - public static void ReportTelemetry() - { - Logger.Log(FunctionId.Workspace_Solution_Info, KeyValueLogMessage.Create(m => - { - m[nameof(UseExistingPartialProjectState)] = s_logAggregator.GetCount(nameof(UseExistingPartialProjectState)); - m[nameof(UseExistingFullProjectState)] = s_logAggregator.GetCount(nameof(UseExistingFullProjectState)); - m[nameof(CreatePartialProjectState)] = s_logAggregator.GetCount(nameof(CreatePartialProjectState)); - m[nameof(UseExistingPartialSolution)] = s_logAggregator.GetCount(nameof(UseExistingPartialSolution)); - m[nameof(CreatePartialSolution)] = s_logAggregator.GetCount(nameof(CreatePartialSolution)); - })); - } - } -} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs index 4bdb07b9528fb..bda48a6b8f124 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs @@ -72,7 +72,7 @@ private SolutionState( _lazyAnalyzers = lazyAnalyzers ?? CreateLazyHostDiagnosticAnalyzers(analyzerReferences); // when solution state is changed, we recalculate its checksum - _lazyChecksums = AsyncLazy.Create(c => ComputeChecksumsAsync(projectsToInclude: null, c)); + _lazyChecksums = AsyncLazy.Create(c => ComputeChecksumsAsync(projectConeId: null, c)); CheckInvariants(); @@ -1038,7 +1038,16 @@ public StateChange WithDocumentSyntaxRoot(DocumentId documentId, SyntaxNode root return UpdateDocumentState(oldDocument.UpdateTree(root, mode), contentChanged: true); } - public StateChange WithDocumentContentsFrom(DocumentId documentId, DocumentState documentState) + /// Whether or not the specified document is forced to have the same text and + /// green-tree-root from . If , then they will share + /// these values. If , then they will only be shared when safe to do so (for example, + /// when parse-options and pp-directives would not cause issues. + /// + /// Forcing should only happen in frozen-partial snapshots, where we are ok with inaccuracies in the trees we + /// get back and want perf to be very high. Any codepaths from frozen-partial should pass for this. Any codepaths from Workspace.UnifyLinkedDocumentContents should pass . + public StateChange WithDocumentContentsFrom(DocumentId documentId, DocumentState documentState, bool forceEvenIfTreesWouldDiffer) { var oldDocument = GetRequiredDocumentState(documentId); var oldProject = GetRequiredProjectState(documentId.ProjectId); @@ -1052,7 +1061,7 @@ public StateChange WithDocumentContentsFrom(DocumentId documentId, DocumentState } return UpdateDocumentState( - oldDocument.UpdateTextAndTreeContents(documentState.TextAndVersionSource, documentState.TreeSource), + oldDocument.UpdateTextAndTreeContents(documentState.TextAndVersionSource, documentState.TreeSource, forceEvenIfTreesWouldDiffer), contentChanged: true); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs new file mode 100644 index 0000000000000..aab3676fde706 --- /dev/null +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs @@ -0,0 +1,179 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Remote; +using Microsoft.CodeAnalysis.Serialization; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis; + +internal partial class SolutionState +{ + private static readonly ConditionalWeakTable, IReadOnlyList> s_projectIdToSortedProjectsMap = new(); + + /// + /// Checksum representing the full checksum tree for this solution compilation state. Includes the checksum for + /// . + /// + private readonly AsyncLazy _lazyChecksums; + + /// + /// Mapping from project-id to the checksums needed to synchronize it (and the projects it depends on) over + /// to an OOP host. Lock this specific field before reading/writing to it. + /// + private readonly Dictionary> _lazyProjectChecksums = new(); + + public static IReadOnlyList GetOrCreateSortedProjectIds(IReadOnlyList unorderedList) + => s_projectIdToSortedProjectsMap.GetValue(unorderedList, projectIds => projectIds.OrderBy(id => id.Id).ToImmutableArray()); + + public bool TryGetStateChecksums([NotNullWhen(true)] out SolutionStateChecksums? stateChecksums) + => _lazyChecksums.TryGetValue(out stateChecksums); + + public bool TryGetStateChecksums(ProjectId projectId, [NotNullWhen(true)] out SolutionStateChecksums? stateChecksums) + { + AsyncLazy? checksums; + lock (_lazyProjectChecksums) + { + if (!_lazyProjectChecksums.TryGetValue(projectId, out checksums) || + checksums == null) + { + stateChecksums = null; + return false; + } + } + + return checksums.TryGetValue(out stateChecksums); + } + + public Task GetStateChecksumsAsync(CancellationToken cancellationToken) + => _lazyChecksums.GetValueAsync(cancellationToken); + + public async Task GetChecksumAsync(CancellationToken cancellationToken) + { + var collection = await GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false); + return collection.Checksum; + } + + /// Gets the checksum for only the requested project (and any project it depends on) + public async Task GetStateChecksumsAsync( + ProjectId projectId, + CancellationToken cancellationToken) + { + Contract.ThrowIfNull(projectId); + + AsyncLazy? checksums; + lock (_lazyProjectChecksums) + { + if (!_lazyProjectChecksums.TryGetValue(projectId, out checksums)) + { + checksums = Compute(projectId); + _lazyProjectChecksums.Add(projectId, checksums); + } + } + + var collection = await checksums.GetValueAsync(cancellationToken).ConfigureAwait(false); + return collection; + + // Extracted as a local function to prevent delegate allocations when not needed. + AsyncLazy Compute(ProjectId projectConeId) + { + return AsyncLazy.Create(c => ComputeChecksumsAsync(projectConeId, c)); + } + } + + /// Gets the checksum for only the requested project (and any project it depends on) + public async Task GetChecksumAsync(ProjectId projectId, CancellationToken cancellationToken) + { + var checksums = await GetStateChecksumsAsync(projectId, cancellationToken).ConfigureAwait(false); + return checksums.Checksum; + } + + /// Cone of projects to compute a checksum for. Pass in to get a + /// checksum for the entire solution + private async Task ComputeChecksumsAsync( + ProjectId? projectConeId, + CancellationToken cancellationToken) + { + using var projectCone = SharedPools.Default>().GetPooledObject(); + AddProjectCone(projectConeId); + + try + { + using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, this.FilePath, cancellationToken)) + { + // get states by id order to have deterministic checksum. Limit expensive computation to the + // requested set of projects if applicable. + var orderedProjectIds = GetOrCreateSortedProjectIds(this.ProjectIds); + + using var _ = ArrayBuilder>.GetInstance(out var projectChecksumTasks); + + foreach (var orderedProjectId in orderedProjectIds) + { + var projectState = this.ProjectStates[orderedProjectId]; + if (!RemoteSupportedLanguages.IsSupported(projectState.Language)) + continue; + + if (projectConeId != null && !projectCone.Object.Contains(orderedProjectId)) + continue; + + projectChecksumTasks.Add(projectState.GetStateChecksumsAsync(cancellationToken)); + } + + var allResults = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false); + + var projectChecksums = allResults.SelectAsArray(r => r.Checksum); + var projectIds = allResults.SelectAsArray(r => r.ProjectId); + + var analyzerReferenceChecksums = ChecksumCache.GetOrCreateChecksumCollection( + this.AnalyzerReferences, this.Services.GetRequiredService(), cancellationToken); + + return new SolutionStateChecksums( + projectConeId, + this.SolutionAttributes.Checksum, + new(new ChecksumCollection(projectChecksums), projectIds), + analyzerReferenceChecksums); + } + } + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) + { + throw ExceptionUtilities.Unreachable(); + } + + void AddProjectCone(ProjectId? projectConeId) + { + if (projectConeId is null) + return; + + if (!projectCone.Object.Add(projectConeId)) + return; + + var projectState = this.GetProjectState(projectConeId); + if (projectState == null) + return; + + foreach (var refProject in projectState.ProjectReferences) + { + // Note: it's possible in the workspace to see project-ids that don't have a corresponding project + // state. While not desirable, we allow project's to have refs to projects that no longer exist + // anymore. This state is expected to be temporary until the project is explicitly told by the + // host to remove the reference. We do not expose this through the full Solution/Project which + // filters out this case already (in Project.ProjectReferences). However, becausde we're at the + // ProjectState level it cannot do that filtering unless examined through us (the SolutionState). + if (this.ProjectStates.ContainsKey(refProject.ProjectId)) + AddProjectCone(refProject.ProjectId); + } + } + } +} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratedDocumentIdentity.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratedDocumentIdentity.cs index 7385848fa0e09..e94a2402fab9d 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratedDocumentIdentity.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SourceGeneratedDocumentIdentity.cs @@ -89,12 +89,12 @@ internal static SourceGeneratedDocumentIdentity ReadFrom(ObjectReader reader) { var documentId = DocumentId.ReadFrom(reader); - var hintName = reader.ReadString(); - var generatorAssemblyName = reader.ReadString(); + var hintName = reader.ReadRequiredString(); + var generatorAssemblyName = reader.ReadRequiredString(); var generatorAssemblyPath = reader.ReadString(); - var generatorAssemblyVersion = Version.Parse(reader.ReadString()); - var generatorTypeName = reader.ReadString(); - var filePath = reader.ReadString(); + var generatorAssemblyVersion = Version.Parse(reader.ReadRequiredString()); + var generatorTypeName = reader.ReadRequiredString(); + var filePath = reader.ReadRequiredString(); return new SourceGeneratedDocumentIdentity( documentId, diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs b/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs index 57e438c82c4e6..b662020217395 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs @@ -97,16 +97,23 @@ public async Task FindAsync( } } +/// The particular if this was a checksum tree made for a particular +/// project cone. internal sealed class SolutionStateChecksums( + ProjectId? projectConeId, Checksum attributes, ChecksumsAndIds projects, ChecksumCollection analyzerReferences) { - public Checksum Checksum { get; } = Checksum.Create( + public Checksum Checksum { get; } = Checksum.Create(stackalloc[] + { + projectConeId == null ? Checksum.Null : projectConeId.Checksum, attributes, projects.Checksum, - analyzerReferences.Checksum); + analyzerReferences.Checksum, + }); + public ProjectId? ProjectConeId { get; } = projectConeId; public Checksum Attributes { get; } = attributes; public ChecksumsAndIds Projects { get; } = projects; public ChecksumCollection AnalyzerReferences { get; } = analyzerReferences; @@ -123,6 +130,9 @@ public void Serialize(ObjectWriter writer) { // Writing this is optional, but helps ensure checksums are being computed properly on both the host and oop side. this.Checksum.WriteTo(writer); + writer.WriteBoolean(this.ProjectConeId != null); + this.ProjectConeId?.WriteTo(writer); + this.Attributes.WriteTo(writer); this.Projects.WriteTo(writer); this.AnalyzerReferences.WriteTo(writer); @@ -131,7 +141,9 @@ public void Serialize(ObjectWriter writer) public static SolutionStateChecksums Deserialize(ObjectReader reader) { var checksum = Checksum.ReadFrom(reader); + var result = new SolutionStateChecksums( + projectConeId: reader.ReadBoolean() ? ProjectId.ReadFrom(reader) : null, attributes: Checksum.ReadFrom(reader), projects: ChecksumsAndIds.ReadFrom(reader), analyzerReferences: ChecksumCollection.ReadFrom(reader)); diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index 94b33b859a9c9..b4895c4ba09b0 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -212,7 +212,7 @@ internal bool SetCurrentSolution( /// updated by to be passed to the workspace change event. /// True if was set to the transformed solution, false if the /// transformation did not change the solution. - private protected (bool updated, Solution newSolution) SetCurrentSolution( + internal (bool updated, Solution newSolution) SetCurrentSolution( Func transformation, Func changeKind, Action? onBeforeUpdate = null, @@ -313,7 +313,7 @@ static Solution UpdateAddedDocumentToExistingContentsInSolution(Solution solutio foreach (var relatedDocumentId in relatedDocumentIds) { var relatedDocument = solution.GetRequiredDocument(relatedDocumentId); - return solution.WithDocumentContentsFrom(addedDocumentId, relatedDocument.DocumentState); + return solution.WithDocumentContentsFrom(addedDocumentId, relatedDocument.DocumentState, forceEvenIfTreesWouldDiffer: false); } return solution; @@ -330,7 +330,7 @@ static Solution UpdateExistingDocumentsToChangedDocumentContents(Solution soluti foreach (var relatedDocumentId in relatedDocumentIds) { if (processedDocuments.Add(relatedDocumentId)) - solution = solution.WithDocumentContentsFrom(relatedDocumentId, changedDocument.DocumentState); + solution = solution.WithDocumentContentsFrom(relatedDocumentId, changedDocument.DocumentState, forceEvenIfTreesWouldDiffer: false); } } @@ -1154,7 +1154,7 @@ private void OnAnyDocumentTextChanged( foreach (var linkedDocumentId in linkedDocumentIds) { previousSolution = newSolution; - newSolution = newSolution.WithDocumentContentsFrom(linkedDocumentId, newDocument.DocumentState); + newSolution = newSolution.WithDocumentContentsFrom(linkedDocumentId, newDocument.DocumentState, forceEvenIfTreesWouldDiffer: false); if (previousSolution != newSolution) updatedDocumentIds.Add(linkedDocumentId); diff --git a/src/Workspaces/Core/Portable/Workspace/WorkspaceDiagnosticDescriptors.cs b/src/Workspaces/Core/Portable/Workspace/WorkspaceDiagnosticDescriptors.cs index 4099714c141ec..91d6169853df8 100644 --- a/src/Workspaces/Core/Portable/Workspace/WorkspaceDiagnosticDescriptors.cs +++ b/src/Workspaces/Core/Portable/Workspace/WorkspaceDiagnosticDescriptors.cs @@ -21,7 +21,7 @@ static WorkspaceDiagnosticDescriptors() category: WorkspacesResources.Workspace_error, defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true, - customTags: new[] { WellKnownDiagnosticTags.NotConfigurable }); + customTags: [WellKnownDiagnosticTags.NotConfigurable]); } } } diff --git a/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs b/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs index e4d4f72a80dc0..4b5a2c31e6c13 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs @@ -1321,8 +1321,7 @@ End Module await VerifyAsync(code, expected); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69696")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69696")] public async Task LineContinuationInString2() { var code = $@"[| @@ -1343,8 +1342,7 @@ End Module await VerifyAsync(code, expected); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/issues/69696")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69696")] public async Task LineContinuationInString3() { var code = $@"[| diff --git a/src/Workspaces/CoreTest/Differencing/MatchTests.cs b/src/Workspaces/CoreTest/Differencing/MatchTests.cs index 15c0ecc3a9089..fadfcfdc0fb48 100644 --- a/src/Workspaces/CoreTest/Differencing/MatchTests.cs +++ b/src/Workspaces/CoreTest/Differencing/MatchTests.cs @@ -24,13 +24,13 @@ public void KnownMatches() x2 = new TestNode(1, 2)); var m = TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, - new[] { KeyValuePairUtil.Create(x1, x2), KeyValuePairUtil.Create(x1, x2) }); + [KeyValuePairUtil.Create(x1, x2), KeyValuePairUtil.Create(x1, x2)]); Assert.True(m.TryGetNewNode(x1, out var n)); Assert.Equal(n, x2); - Assert.Throws(() => TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, new[] { KeyValuePairUtil.Create(x1, x1) })); + Assert.Throws(() => TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, [KeyValuePairUtil.Create(x1, x1)])); - Assert.Throws(() => TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, new[] { KeyValuePairUtil.Create(x1, x2), KeyValuePairUtil.Create(x1, new TestNode(0, 0)) })); + Assert.Throws(() => TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, [KeyValuePairUtil.Create(x1, x2), KeyValuePairUtil.Create(x1, new TestNode(0, 0))])); } [Fact] @@ -46,11 +46,11 @@ public void KnownMatchesDups() x2 = new TestNode(1, 2), y2 = new TestNode(1, 3)); - var m = TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, new[] - { + var m = TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, + [ KeyValuePairUtil.Create(x1, x2), KeyValuePairUtil.Create(y1, x2), - }); + ]); // the first one wins: Assert.True(m.TryGetNewNode(x1, out var n)); @@ -72,10 +72,10 @@ public void KnownMatchesRootMatch() var newRoot = new TestNode(0, 1, x2 = new TestNode(0, 2)); - var m = TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, new[] - { + var m = TestTreeComparer.Instance.ComputeMatch(oldRoot, newRoot, + [ KeyValuePairUtil.Create(x1, newRoot), - }); + ]); // the root wins: Assert.True(m.TryGetNewNode(x1, out var n)); // matched diff --git a/src/Workspaces/CoreTest/ExtensionOrdererTests.cs b/src/Workspaces/CoreTest/ExtensionOrdererTests.cs index b37437aeab86c..61658bff23712 100644 --- a/src/Workspaces/CoreTest/ExtensionOrdererTests.cs +++ b/src/Workspaces/CoreTest/ExtensionOrdererTests.cs @@ -17,10 +17,10 @@ private class Extension { } [Fact] public void TestNoCycle1() { - var a = CreateExtension(name: "a", before: new[] { "b" }); - var b = CreateExtension(name: "b", before: new[] { "c" }); - var c = CreateExtension(name: "c", before: new[] { "d" }); - var d = CreateExtension(name: "d", before: new[] { "e" }); + var a = CreateExtension(name: "a", before: ["b"]); + var b = CreateExtension(name: "b", before: ["c"]); + var c = CreateExtension(name: "c", before: ["d"]); + var d = CreateExtension(name: "d", before: ["e"]); var e = CreateExtension(name: "e"); var extensions = new List>() { d, b, a, c, e }; @@ -34,10 +34,10 @@ public void TestNoCycle1() [Fact] public void TestNoCycle2() { - var a = CreateExtension(name: "a", after: new[] { "b" }); - var b = CreateExtension(name: "b", after: new[] { "c" }); - var c = CreateExtension(name: "c", after: new[] { "d" }); - var d = CreateExtension(name: "d", after: new[] { "e" }); + var a = CreateExtension(name: "a", after: ["b"]); + var b = CreateExtension(name: "b", after: ["c"]); + var c = CreateExtension(name: "c", after: ["d"]); + var d = CreateExtension(name: "d", after: ["e"]); var e = CreateExtension(name: "e"); var extensions = new List>() { d, b, a, c, e }; @@ -51,11 +51,11 @@ public void TestNoCycle2() [Fact] public void TestNoCycle3() { - var a = CreateExtension(name: "a", before: new[] { "b", "c", "d", "e" }); - var b = CreateExtension(name: "b", before: new[] { "c", "d", "e" }, after: new[] { "a" }); - var c = CreateExtension(name: "c", before: new[] { "d", "e" }, after: new[] { "b", "a" }); - var d = CreateExtension(name: "d", before: new[] { "e" }, after: new[] { "c", "b", "a" }); - var e = CreateExtension(name: "e", after: new[] { "d", "c", "b", "a" }); + var a = CreateExtension(name: "a", before: ["b", "c", "d", "e"]); + var b = CreateExtension(name: "b", before: ["c", "d", "e"], after: ["a"]); + var c = CreateExtension(name: "c", before: ["d", "e"], after: ["b", "a"]); + var d = CreateExtension(name: "d", before: ["e"], after: ["c", "b", "a"]); + var e = CreateExtension(name: "e", after: ["d", "c", "b", "a"]); var extensions = new List>() { d, b, a, c, e }; @@ -68,11 +68,11 @@ public void TestNoCycle3() [Fact] public void TestCycle1() { - var a = CreateExtension(name: "a", before: new[] { "b" }); - var b = CreateExtension(name: "b", before: new[] { "c" }); - var c = CreateExtension(name: "c", before: new[] { "d" }); - var d = CreateExtension(name: "d", before: new[] { "e" }); - var e = CreateExtension(name: "e", before: new[] { "a" }); + var a = CreateExtension(name: "a", before: ["b"]); + var b = CreateExtension(name: "b", before: ["c"]); + var c = CreateExtension(name: "c", before: ["d"]); + var d = CreateExtension(name: "d", before: ["e"]); + var e = CreateExtension(name: "e", before: ["a"]); var extensions = new List>() { a, b, c, d, e }; @@ -85,11 +85,11 @@ public void TestCycle1() [Fact] public void TestCycle2() { - var a = CreateExtension(name: "a", after: new[] { "b" }); - var b = CreateExtension(name: "b", after: new[] { "c" }); - var c = CreateExtension(name: "c", after: new[] { "d" }); - var d = CreateExtension(name: "d", after: new[] { "e" }); - var e = CreateExtension(name: "e", after: new[] { "a" }); + var a = CreateExtension(name: "a", after: ["b"]); + var b = CreateExtension(name: "b", after: ["c"]); + var c = CreateExtension(name: "c", after: ["d"]); + var d = CreateExtension(name: "d", after: ["e"]); + var e = CreateExtension(name: "e", after: ["a"]); var extensions = new List>() { a, b, c, d, e }; @@ -103,7 +103,7 @@ public void TestCycle2() public void TestCycle3() { var a = CreateExtension(name: "a"); - var b = CreateExtension(name: "b", before: new[] { "a" }, after: new[] { "a" }); + var b = CreateExtension(name: "b", before: ["a"], after: ["a"]); var c = CreateExtension(name: "c"); var extensions = new List>() { a, b, c }; @@ -118,7 +118,7 @@ public void TestCycle3() public void TestCycle4() { var a = CreateExtension(name: "a"); - var b = CreateExtension(name: "b", before: new[] { "b" }, after: new[] { "b" }); + var b = CreateExtension(name: "b", before: ["b"], after: ["b"]); var c = CreateExtension(name: "c"); var extensions = new List>() { a, b, c }; @@ -132,12 +132,12 @@ public void TestCycle4() [Fact] public void TestCycle5() { - var a = CreateExtension(name: "a", before: new[] { "b" }); - var b = CreateExtension(name: "b", before: new[] { "c" }); - var c = CreateExtension(name: "c", before: new[] { "d" }); - var d = CreateExtension(name: "d", before: new[] { "e" }); - var e = CreateExtension(name: "e", before: new[] { "c" }); - var f = CreateExtension(name: "f", before: new[] { "g" }); + var a = CreateExtension(name: "a", before: ["b"]); + var b = CreateExtension(name: "b", before: ["c"]); + var c = CreateExtension(name: "c", before: ["d"]); + var d = CreateExtension(name: "d", before: ["e"]); + var e = CreateExtension(name: "e", before: ["c"]); + var f = CreateExtension(name: "f", before: ["g"]); var g = CreateExtension(name: "g"); var extensions = new List>() { a, b, c, d, e, f, g }; @@ -151,12 +151,12 @@ public void TestCycle5() [Fact] public void TestCycle6() { - var a = CreateExtension(name: "a", before: new[] { "b" }); - var b = CreateExtension(name: "b", before: new[] { "c" }); - var c = CreateExtension(name: "c", before: new[] { "d" }); - var d = CreateExtension(name: "d", before: new[] { "e" }); - var e = CreateExtension(name: "e", before: new[] { "a" }); - var f = CreateExtension(name: "f", before: new[] { "g" }); + var a = CreateExtension(name: "a", before: ["b"]); + var b = CreateExtension(name: "b", before: ["c"]); + var c = CreateExtension(name: "c", before: ["d"]); + var d = CreateExtension(name: "d", before: ["e"]); + var e = CreateExtension(name: "e", before: ["a"]); + var f = CreateExtension(name: "f", before: ["g"]); var g = CreateExtension(name: "g"); var extensions = new List>() { a, b, c, d, e, f, g }; @@ -170,12 +170,12 @@ public void TestCycle6() [Fact] public void TestCycle7() { - var a = CreateExtension(name: "a", before: new[] { "b" }); - var b = CreateExtension(name: "b", before: new[] { "c" }); - var c = CreateExtension(name: "c", before: new[] { "a" }); - var d = CreateExtension(name: "d", before: new[] { "e" }); - var e = CreateExtension(name: "e", before: new[] { "f" }); - var f = CreateExtension(name: "f", before: new[] { "d" }); + var a = CreateExtension(name: "a", before: ["b"]); + var b = CreateExtension(name: "b", before: ["c"]); + var c = CreateExtension(name: "c", before: ["a"]); + var d = CreateExtension(name: "d", before: ["e"]); + var e = CreateExtension(name: "e", before: ["f"]); + var f = CreateExtension(name: "f", before: ["d"]); var extensions = new List>() { a, b, c, d, e, f }; @@ -188,12 +188,12 @@ public void TestCycle7() [Fact] public void TestCycle8() { - var a = CreateExtension(name: "a", before: new[] { "b" }); - var b = CreateExtension(name: "b", before: new[] { "c" }); - var c = CreateExtension(name: "c", before: new[] { "d" }); - var d = CreateExtension(name: "d", before: new[] { "e", "c" }); - var e = CreateExtension(name: "e", before: new[] { "f" }); - var f = CreateExtension(name: "f", before: new[] { "a" }); + var a = CreateExtension(name: "a", before: ["b"]); + var b = CreateExtension(name: "b", before: ["c"]); + var c = CreateExtension(name: "c", before: ["d"]); + var d = CreateExtension(name: "d", before: ["e", "c"]); + var e = CreateExtension(name: "e", before: ["f"]); + var f = CreateExtension(name: "f", before: ["a"]); var extensions = new List>() { a, b, c, d, e, f }; diff --git a/src/Workspaces/CoreTest/FindReferencesTests.cs b/src/Workspaces/CoreTest/FindReferencesTests.cs index 0decd2303fe97..f7727b83ed557 100644 --- a/src/Workspaces/CoreTest/FindReferencesTests.cs +++ b/src/Workspaces/CoreTest/FindReferencesTests.cs @@ -34,7 +34,7 @@ private static Solution AddProjectWithMetadataReferences(Solution solution, stri projectName, projectName, languageName, - metadataReferences: new[] { metadataReference }, + metadataReferences: [metadataReference], projectReferences: projectReferences.Select(p => new ProjectReference(p))); return solution.AddProject(pi).AddDocument(did, $"{projectName}.{suffix}", SourceText.From(code)); } @@ -369,7 +369,7 @@ public System.Uri Get() }", SystemRef_v46, solution.Projects.Single(pid => pid.Name == "NetStandardProject").Id); var desktopProject = solution.Projects.First(p => p.Name == "DesktopProject"); - solution = solution.AddMetadataReferences(desktopProject.Id, new[] { MscorlibRef_v46, Net46StandardFacade }); + solution = solution.AddMetadataReferences(desktopProject.Id, [MscorlibRef_v46, Net46StandardFacade]); desktopProject = solution.GetProject(desktopProject.Id); var netStandardProject = solution.Projects.First(p => p.Name == "NetStandardProject"); @@ -416,7 +416,7 @@ interface ITestBase using var workspace = CreateWorkspace(); var solution = GetMultipleDocumentSolution(workspace, [implText, interface1Text, interface2Text]); - solution = solution.AddMetadataReferences(solution.ProjectIds.Single(), new[] { MscorlibRef_v46, Net46StandardFacade, SystemRef_v46, NetStandard20Ref }); + solution = solution.AddMetadataReferences(solution.ProjectIds.Single(), [MscorlibRef_v46, Net46StandardFacade, SystemRef_v46, NetStandard20Ref]); var project = solution.Projects.Single(); var compilation = await project.GetCompilationAsync(); diff --git a/src/Workspaces/CoreTest/ObjectSerializationTests.cs b/src/Workspaces/CoreTest/ObjectSerializationTests.cs index e7bb2aaac11cb..cb9a3212a377c 100644 --- a/src/Workspaces/CoreTest/ObjectSerializationTests.cs +++ b/src/Workspaces/CoreTest/ObjectSerializationTests.cs @@ -85,16 +85,16 @@ private static T RoundTripValue(T value, bool recursive) { if (v != null && v.GetType().IsEnum) { - w.WriteInt64(Convert.ToInt64((object)v)); + w.WriteInt64(Convert.ToInt64(v)); } else { - w.WriteValue(v); + w.WriteScalarValue(v); } }, r => value != null && value.GetType().IsEnum ? (T)Enum.ToObject(typeof(T), r.ReadInt64()) - : (T)r.ReadValue(), recursive); + : (T)r.ReadScalarValue(), recursive); } private static void TestRoundTripValue(T value, bool recursive) @@ -159,7 +159,7 @@ public void WriteTo(ObjectWriter writer) } else { - writer.WriteValue(_member); + writer.WriteScalarValue(_member); } } @@ -222,19 +222,6 @@ public void TestUInt32TypeCodes() Assert.Equal(ObjectWriter.TypeCode.UInt32_10, ObjectWriter.TypeCode.UInt32_0 + 10); } - private static void TestRoundTripType(Type type) - { - TestRoundTrip(type, (w, v) => w.WriteType(v), r => r.ReadType()); - } - - [Fact] - public void TestTypes() - { - TestRoundTripType(typeof(int)); - TestRoundTripType(typeof(string)); - TestRoundTripType(typeof(ObjectSerializationTests)); - } - private static void TestRoundTripCompressedUint(uint value) { TestRoundTrip(value, (w, v) => ((ObjectWriter)w).WriteCompressedUInt(v), r => ((ObjectReader)r).ReadCompressedUInt()); @@ -259,41 +246,6 @@ public void TestCompressedUInt() Assert.Throws(() => TestRoundTripCompressedUint(0xC0000000u)); // both high bits set not allowed } - [Fact] - public void TestArraySizes() - { - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1, 2, 3, 4, 5); - TestArrayValues(1m, 2m, 3m, 4m, 5m); - TestArrayValues(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); - TestArrayValues(1.0, 2.0, 3.0, 4.0, 5.0); - TestArrayValues('1', '2', '3', '4', '5'); - TestArrayValues("1", "2", "3", "4", "5"); - } - - private static void TestArrayValues(T v1, T v2, T v3, T v4, T v5) - { - TestRoundTripValue((T[])null); - TestRoundTripValue(new T[] { }); - TestRoundTripValue(new T[] { v1 }); - TestRoundTripValue(new T[] { v1, v2 }); - TestRoundTripValue(new T[] { v1, v2, v3 }); - TestRoundTripValue(new T[] { v1, v2, v3, v4 }); - TestRoundTripValue(new T[] { v1, v2, v3, v4, v5 }); - } - - [Fact] - public void TestPrimitiveArrayValues() - { - TestRoundTrip(w => TestWritingPrimitiveArrays(w), r => TestReadingPrimitiveArrays(r)); - } - [Theory] [CombinatorialData] public void TestByteSpan([CombinatorialValues(0, 1, 2, 3, 1000, 1000000)] int size) @@ -307,103 +259,14 @@ public void TestByteSpan([CombinatorialValues(0, 1, 2, 3, 1000, 1000000)] int si TestRoundTrip(w => TestWritingByteSpan(data, w), r => TestReadingByteSpan(data, r)); } - private static void TestWritingPrimitiveArrays(ObjectWriter writer) - { - var inputBool = new bool[] { true, false }; - var inputByte = new byte[] { 1, 2, 3, 4, 5 }; - var inputChar = new char[] { 'h', 'e', 'l', 'l', 'o' }; - var inputDecimal = new decimal[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M }; - var inputDouble = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0 }; - var inputFloat = new float[] { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F }; - var inputInt = new int[] { -1, -2, -3, -4, -5 }; - var inputLong = new long[] { 1, 2, 3, 4, 5 }; - var inputSByte = new sbyte[] { -1, -2, -3, -4, -5 }; - var inputShort = new short[] { -1, -2, -3, -4, -5 }; - var inputUInt = new uint[] { 1, 2, 3, 4, 5 }; - var inputULong = new ulong[] { 1, 2, 3, 4, 5 }; - var inputUShort = new ushort[] { 1, 2, 3, 4, 5 }; - var inputString = new string[] { "h", "e", "l", "l", "o" }; - - writer.WriteValue(inputBool); - writer.WriteValue((object)inputByte); - writer.WriteValue(inputChar); - writer.WriteValue(inputDecimal); - writer.WriteValue(inputDouble); - writer.WriteValue(inputFloat); - writer.WriteValue(inputInt); - writer.WriteValue(inputLong); - writer.WriteValue(inputSByte); - writer.WriteValue(inputShort); - writer.WriteValue(inputUInt); - writer.WriteValue(inputULong); - writer.WriteValue(inputUShort); - writer.WriteValue(inputString); - } - - private static void TestReadingPrimitiveArrays(ObjectReader reader) - { - var inputBool = new bool[] { true, false }; - var inputByte = new byte[] { 1, 2, 3, 4, 5 }; - var inputChar = new char[] { 'h', 'e', 'l', 'l', 'o' }; - var inputDecimal = new decimal[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M }; - var inputDouble = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0 }; - var inputFloat = new float[] { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F }; - var inputInt = new int[] { -1, -2, -3, -4, -5 }; - var inputLong = new long[] { 1, 2, 3, 4, 5 }; - var inputSByte = new sbyte[] { -1, -2, -3, -4, -5 }; - var inputShort = new short[] { -1, -2, -3, -4, -5 }; - var inputUInt = new uint[] { 1, 2, 3, 4, 5 }; - var inputULong = new ulong[] { 1, 2, 3, 4, 5 }; - var inputUShort = new ushort[] { 1, 2, 3, 4, 5 }; - var inputString = new string[] { "h", "e", "l", "l", "o" }; - - Assert.True(Enumerable.SequenceEqual(inputBool, (bool[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputByte, (byte[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputChar, (char[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputDecimal, (decimal[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputDouble, (double[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputFloat, (float[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputInt, (int[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputLong, (long[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputSByte, (sbyte[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputShort, (short[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputUInt, (uint[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputULong, (ulong[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputUShort, (ushort[])reader.ReadValue())); - Assert.True(Enumerable.SequenceEqual(inputString, (string[])reader.ReadValue())); - } - private static void TestWritingByteSpan(byte[] data, ObjectWriter writer) { - writer.WriteValue(data.AsSpan()); + writer.WriteSpan(data.AsSpan()); } private static void TestReadingByteSpan(byte[] expected, ObjectReader reader) { - Assert.True(Enumerable.SequenceEqual(expected, (byte[])reader.ReadValue())); - } - - [Fact] - public void TestBooleanArrays() - { - for (var i = 0; i < 1000; i++) - { - var inputBool = new bool[i]; - - for (var j = 0; j < i; j++) - { - inputBool[j] = j % 2 == 0; - } - - TestRoundTripValue(inputBool); - } - } - - [Fact] - public void TestFalseBooleanArray() - { - var inputBool = Enumerable.Repeat(false, 1000).ToArray(); - TestRoundTripValue(inputBool); + Assert.True(Enumerable.SequenceEqual(expected, (byte[])reader.ReadByteArray())); } private static readonly DateTime _testNow = DateTime.Now; @@ -600,32 +463,27 @@ public void TestPrimitivesValue() private static void TestWritingPrimitiveValues(ObjectWriter writer) { - writer.WriteValue(true); - writer.WriteValue(false); - writer.WriteValue(Byte.MaxValue); - writer.WriteValue(SByte.MaxValue); - writer.WriteValue(Int16.MaxValue); - writer.WriteValue(Int32.MaxValue); - writer.WriteValue((Int32)Byte.MaxValue); - writer.WriteValue((Int32)Int16.MaxValue); - writer.WriteValue(Int64.MaxValue); - writer.WriteValue(UInt16.MaxValue); - writer.WriteValue(UInt32.MaxValue); - writer.WriteValue(UInt64.MaxValue); - writer.WriteValue(Decimal.MaxValue); - writer.WriteValue(Double.MaxValue); - writer.WriteValue(Single.MaxValue); - writer.WriteValue('X'); - - writer.WriteValue((object)"YYY"); - - writer.WriteValue((object)"\uD800\uDC00"); // valid surrogate pair - - writer.WriteValue((object)"\uDC00\uD800"); // invalid surrogate pair - - writer.WriteValue((object)"\uD800"); // incomplete surrogate pair - - writer.WriteValue((object)null); + writer.WriteScalarValue(true); + writer.WriteScalarValue(false); + writer.WriteScalarValue(Byte.MaxValue); + writer.WriteScalarValue(SByte.MaxValue); + writer.WriteScalarValue(Int16.MaxValue); + writer.WriteScalarValue(Int32.MaxValue); + writer.WriteScalarValue((Int32)Byte.MaxValue); + writer.WriteScalarValue((Int32)Int16.MaxValue); + writer.WriteScalarValue(Int64.MaxValue); + writer.WriteScalarValue(UInt16.MaxValue); + writer.WriteScalarValue(UInt32.MaxValue); + writer.WriteScalarValue(UInt64.MaxValue); + writer.WriteScalarValue(Decimal.MaxValue); + writer.WriteScalarValue(Double.MaxValue); + writer.WriteScalarValue(Single.MaxValue); + writer.WriteScalarValue('X'); + writer.WriteScalarValue((object)"YYY"); + writer.WriteScalarValue((object)"\uD800\uDC00"); // valid surrogate pair + writer.WriteScalarValue((object)"\uDC00\uD800"); // invalid surrogate pair + writer.WriteScalarValue((object)"\uD800"); // incomplete surrogate pair + writer.WriteScalarValue((object)null); unchecked { writer.WriteInt64((long)ConsoleColor.Cyan); @@ -638,32 +496,32 @@ private static void TestWritingPrimitiveValues(ObjectWriter writer) writer.WriteInt64((long)ELong.Value); writer.WriteInt64((long)EULong.Value); } - writer.WriteValue(_testNow); + writer.WriteScalarValue(_testNow); } private static void TestReadingPrimitiveValues(ObjectReader reader) { - Assert.True((bool)reader.ReadValue()); - Assert.False((bool)reader.ReadValue()); - Assert.Equal(Byte.MaxValue, (Byte)reader.ReadValue()); - Assert.Equal(SByte.MaxValue, (SByte)reader.ReadValue()); - Assert.Equal(Int16.MaxValue, (Int16)reader.ReadValue()); - Assert.Equal(Int32.MaxValue, (Int32)reader.ReadValue()); - Assert.Equal(Byte.MaxValue, (Int32)reader.ReadValue()); - Assert.Equal(Int16.MaxValue, (Int32)reader.ReadValue()); - Assert.Equal(Int64.MaxValue, (Int64)reader.ReadValue()); - Assert.Equal(UInt16.MaxValue, (UInt16)reader.ReadValue()); - Assert.Equal(UInt32.MaxValue, (UInt32)reader.ReadValue()); - Assert.Equal(UInt64.MaxValue, (UInt64)reader.ReadValue()); - Assert.Equal(Decimal.MaxValue, (Decimal)reader.ReadValue()); - Assert.Equal(Double.MaxValue, (Double)reader.ReadValue()); - Assert.Equal(Single.MaxValue, (Single)reader.ReadValue()); - Assert.Equal('X', (Char)reader.ReadValue()); - Assert.Equal("YYY", (String)reader.ReadValue()); - Assert.Equal("\uD800\uDC00", (String)reader.ReadValue()); // valid surrogate pair - Assert.Equal("\uDC00\uD800", (String)reader.ReadValue()); // invalid surrogate pair - Assert.Equal("\uD800", (String)reader.ReadValue()); // incomplete surrogate pair - Assert.Null(reader.ReadValue()); + Assert.True((bool)reader.ReadScalarValue()); + Assert.False((bool)reader.ReadScalarValue()); + Assert.Equal(Byte.MaxValue, (Byte)reader.ReadScalarValue()); + Assert.Equal(SByte.MaxValue, (SByte)reader.ReadScalarValue()); + Assert.Equal(Int16.MaxValue, (Int16)reader.ReadScalarValue()); + Assert.Equal(Int32.MaxValue, (Int32)reader.ReadScalarValue()); + Assert.Equal(Byte.MaxValue, (Int32)reader.ReadScalarValue()); + Assert.Equal(Int16.MaxValue, (Int32)reader.ReadScalarValue()); + Assert.Equal(Int64.MaxValue, (Int64)reader.ReadScalarValue()); + Assert.Equal(UInt16.MaxValue, (UInt16)reader.ReadScalarValue()); + Assert.Equal(UInt32.MaxValue, (UInt32)reader.ReadScalarValue()); + Assert.Equal(UInt64.MaxValue, (UInt64)reader.ReadScalarValue()); + Assert.Equal(Decimal.MaxValue, (Decimal)reader.ReadScalarValue()); + Assert.Equal(Double.MaxValue, (Double)reader.ReadScalarValue()); + Assert.Equal(Single.MaxValue, (Single)reader.ReadScalarValue()); + Assert.Equal('X', (Char)reader.ReadScalarValue()); + Assert.Equal("YYY", (String)reader.ReadScalarValue()); + Assert.Equal("\uD800\uDC00", (String)reader.ReadScalarValue()); // valid surrogate pair + Assert.Equal("\uDC00\uD800", (String)reader.ReadScalarValue()); // invalid surrogate pair + Assert.Equal("\uD800", (String)reader.ReadScalarValue()); // incomplete surrogate pair + Assert.Null(reader.ReadScalarValue()); unchecked { @@ -678,7 +536,7 @@ private static void TestReadingPrimitiveValues(ObjectReader reader) Assert.Equal((long)EULong.Value, reader.ReadInt64()); } - Assert.Equal(_testNow, (DateTime)reader.ReadValue()); + Assert.Equal(_testNow, (DateTime)reader.ReadScalarValue()); } public enum EByte : byte @@ -783,18 +641,6 @@ private static void TestRoundTripStringCharacter(ushort code) TestRoundTripString(new String((char)code, 1)); } - [Fact] - public void TestRoundTripArrays() - { - //TestRoundTripArray(new object[] { }); - //TestRoundTripArray(new object[] { "hello" }); - //TestRoundTripArray(new object[] { "hello", "world" }); - //TestRoundTripArray(new object[] { "hello", "world", "good" }); - //TestRoundTripArray(new object[] { "hello", "world", "good", "bye" }); - //TestRoundTripArray(new object[] { "hello", 123, 45m, 99.9, 'c' }); - TestRoundTripArray(new string[] { "hello", null, "world" }); - } - private static void TestRoundTripArray(T[] values) { TestRoundTripValue(values); @@ -818,7 +664,7 @@ public void Encodings(Encoding original) using var reader = ObjectReader.TryGetReader(stream); Assert.NotNull(reader); - var deserialized = (Encoding)reader.ReadValue(); + var deserialized = reader.ReadEncoding(); EncodingTestHelpers.AssertEncodingsEqual(original, deserialized); } diff --git a/src/Workspaces/CoreTest/SemanticModelReuse/SemanticModelReuseTests.cs b/src/Workspaces/CoreTest/SemanticModelReuse/SemanticModelReuseTests.cs index f0aef4e5cddbb..a7d88427a2a5f 100644 --- a/src/Workspaces/CoreTest/SemanticModelReuse/SemanticModelReuseTests.cs +++ b/src/Workspaces/CoreTest/SemanticModelReuse/SemanticModelReuseTests.cs @@ -208,8 +208,7 @@ public async Task MultipleBodyEditsShouldProduceFreshModel_Accessor_Indexer_CSha Assert.True(model3.IsSpeculativeSemanticModel); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1587699")] public async Task TestOutOfBoundsInSyntaxContext1_CSharp() { @@ -230,8 +229,7 @@ public async Task TestOutOfBoundsInSyntaxContext1_CSharp() CSharpSyntaxContext.CreateContext(document2, model2, source.IndexOf("void"), CancellationToken.None); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1587699")] public async Task TestOutOfBoundsInSyntaxContext2_CSharp() { @@ -509,8 +507,7 @@ end event Assert.True(model3.IsSpeculativeSemanticModel); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1587699")] public async Task TestOutOfBoundsInSyntaxContext1_VisualBasic() { @@ -541,8 +538,7 @@ end sub VisualBasicSyntaxContext.CreateContext(document2, model2, source.IndexOf("sub"), CancellationToken.None); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1541001")] [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1587699")] public async Task TestOutOfBoundsInSyntaxContext2_VisualBasic() { diff --git a/src/Workspaces/CoreTest/Shared/Extensions/TextSpanExtensions/SubtractTests.cs b/src/Workspaces/CoreTest/Shared/Extensions/TextSpanExtensions/SubtractTests.cs index 1923b142bd3aa..3e431a299a4db 100644 --- a/src/Workspaces/CoreTest/Shared/Extensions/TextSpanExtensions/SubtractTests.cs +++ b/src/Workspaces/CoreTest/Shared/Extensions/TextSpanExtensions/SubtractTests.cs @@ -40,7 +40,7 @@ public class SubtractTests : TestBase public void StartingBeforeStartAndEndingBeforeStart() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeStart(LongSpan), RightBeforeStart(LongSpan)))); } @@ -48,7 +48,7 @@ public void StartingBeforeStartAndEndingBeforeStart() public void StartingBeforeStartAndEndingAtStart() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeStart(LongSpan), AtStart(LongSpan)))); } @@ -56,7 +56,7 @@ public void StartingBeforeStartAndEndingAtStart() public void StartingBeforeStartAndEndingAfterStart() { Assert.Equal( - new[] { TextSpan.FromBounds(RightAfterStart(LongSpan), AtEnd(LongSpan)) }, + [TextSpan.FromBounds(RightAfterStart(LongSpan), AtEnd(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeStart(LongSpan), RightAfterStart(LongSpan)))); } @@ -64,7 +64,7 @@ public void StartingBeforeStartAndEndingAfterStart() public void StartingBeforeStartAndEndingBeforeEnd() { Assert.Equal( - new[] { TextSpan.FromBounds(RightBeforeEnd(LongSpan), AtEnd(LongSpan)) }, + [TextSpan.FromBounds(RightBeforeEnd(LongSpan), AtEnd(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeStart(LongSpan), RightBeforeEnd(LongSpan)))); } @@ -86,7 +86,7 @@ public void StartingBeforeStartAndEndingAfterEnd() public void StartingAtStartAndEndingAtStart() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(AtStart(LongSpan), AtStart(LongSpan)))); } @@ -94,7 +94,7 @@ public void StartingAtStartAndEndingAtStart() public void StartingAtStartAndEndingAfterStart() { Assert.Equal( - new[] { TextSpan.FromBounds(RightAfterStart(LongSpan), AtEnd(LongSpan)) }, + [TextSpan.FromBounds(RightAfterStart(LongSpan), AtEnd(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(AtStart(LongSpan), RightAfterStart(LongSpan)))); } @@ -102,7 +102,7 @@ public void StartingAtStartAndEndingAfterStart() public void StartingAtStartAndEndingBeforeEnd() { Assert.Equal( - new[] { TextSpan.FromBounds(RightBeforeEnd(LongSpan), AtEnd(LongSpan)) }, + [TextSpan.FromBounds(RightBeforeEnd(LongSpan), AtEnd(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(AtStart(LongSpan), RightBeforeEnd(LongSpan)))); } @@ -124,7 +124,7 @@ public void StartingAtStartAndEndingAfterEnd() public void StartingAfterStartAndEndingAfterStart() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(RightAfterStart(LongSpan), RightAfterStart(LongSpan)))); } @@ -132,11 +132,10 @@ public void StartingAfterStartAndEndingAfterStart() public void StartingAfterStartAndEndingBeforeEnd() { Assert.Equal( - new[] - { + [ TextSpan.FromBounds(AtStart(LongSpan), RightAfterStart(LongSpan)), TextSpan.FromBounds(RightBeforeEnd(LongSpan), AtEnd(LongSpan)) - }, + ], LongSpan.Subtract(TextSpan.FromBounds(RightAfterStart(LongSpan), RightBeforeEnd(LongSpan)))); } @@ -144,7 +143,7 @@ public void StartingAfterStartAndEndingBeforeEnd() public void StartingAfterStartAndEndingAtEnd() { Assert.Equal( - new[] { TextSpan.FromBounds(AtStart(LongSpan), RightAfterStart(LongSpan)) }, + [TextSpan.FromBounds(AtStart(LongSpan), RightAfterStart(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(RightAfterStart(LongSpan), AtEnd(LongSpan)))); } @@ -152,7 +151,7 @@ public void StartingAfterStartAndEndingAtEnd() public void StartingAfterStartAndEndingAfterEnd() { Assert.Equal( - new[] { TextSpan.FromBounds(AtStart(LongSpan), RightAfterStart(LongSpan)) }, + [TextSpan.FromBounds(AtStart(LongSpan), RightAfterStart(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(RightAfterStart(LongSpan), RightAfterEnd(LongSpan)))); } @@ -160,7 +159,7 @@ public void StartingAfterStartAndEndingAfterEnd() public void StartingBeforeEndAndEndingBeforeEnd() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeEnd(LongSpan), RightBeforeEnd(LongSpan)))); } @@ -168,7 +167,7 @@ public void StartingBeforeEndAndEndingBeforeEnd() public void StartingBeforeEndAndEndingAtEnd() { Assert.Equal( - new[] { TextSpan.FromBounds(AtStart(LongSpan), RightBeforeEnd(LongSpan)) }, + [TextSpan.FromBounds(AtStart(LongSpan), RightBeforeEnd(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeEnd(LongSpan), AtEnd(LongSpan)))); } @@ -176,7 +175,7 @@ public void StartingBeforeEndAndEndingAtEnd() public void StartingBeforeEndAndEndingAfterEnd() { Assert.Equal( - new[] { TextSpan.FromBounds(AtStart(LongSpan), RightBeforeEnd(LongSpan)) }, + [TextSpan.FromBounds(AtStart(LongSpan), RightBeforeEnd(LongSpan))], LongSpan.Subtract(TextSpan.FromBounds(RightBeforeEnd(LongSpan), RightAfterEnd(LongSpan)))); } @@ -184,7 +183,7 @@ public void StartingBeforeEndAndEndingAfterEnd() public void StartingAtEndAndEndingAtEnd() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(AtEnd(LongSpan), AtEnd(LongSpan)))); } @@ -192,7 +191,7 @@ public void StartingAtEndAndEndingAtEnd() public void StartingAtEndAndEndingAfterEnd() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(AtEnd(LongSpan), RightAfterEnd(LongSpan)))); } @@ -200,7 +199,7 @@ public void StartingAtEndAndEndingAfterEnd() public void StartingAfterEndAndEndingAfterEnd() { Assert.Equal( - new[] { LongSpan }, + [LongSpan], LongSpan.Subtract(TextSpan.FromBounds(RightAfterEnd(LongSpan), RightAfterEnd(LongSpan)))); } @@ -208,7 +207,7 @@ public void StartingAfterEndAndEndingAfterEnd() public void UnitSpanStartingBeforeStartAndEndingBeforeStart() { Assert.Equal( - new[] { UnitSpan }, + [UnitSpan], UnitSpan.Subtract(TextSpan.FromBounds(RightBeforeStart(UnitSpan), RightBeforeStart(UnitSpan)))); } @@ -216,7 +215,7 @@ public void UnitSpanStartingBeforeStartAndEndingBeforeStart() public void UnitSpanStartingBeforeStartAndEndingAtStart() { Assert.Equal( - new[] { UnitSpan }, + [UnitSpan], UnitSpan.Subtract(TextSpan.FromBounds(RightBeforeStart(UnitSpan), AtStart(UnitSpan)))); } @@ -238,7 +237,7 @@ public void UnitSpanStartingBeforeStartAndEndingAfterEnd() public void UnitSpanStartingAtStartAndEndingAtStart() { Assert.Equal( - new[] { UnitSpan }, + [UnitSpan], UnitSpan.Subtract(TextSpan.FromBounds(AtStart(UnitSpan), AtStart(UnitSpan)))); } @@ -260,7 +259,7 @@ public void UnitSpanStartingAtStartAndEndingAfterEnd() public void UnitSpanStartingAtEndAndEndingAtEnd() { Assert.Equal( - new[] { UnitSpan }, + [UnitSpan], UnitSpan.Subtract(TextSpan.FromBounds(AtEnd(UnitSpan), AtEnd(UnitSpan)))); } @@ -268,7 +267,7 @@ public void UnitSpanStartingAtEndAndEndingAtEnd() public void UnitSpanStartingAtEndAndEndingAfterEnd() { Assert.Equal( - new[] { UnitSpan }, + [UnitSpan], UnitSpan.Subtract(TextSpan.FromBounds(AtEnd(UnitSpan), RightAfterEnd(UnitSpan)))); } @@ -276,7 +275,7 @@ public void UnitSpanStartingAtEndAndEndingAfterEnd() public void UnitSpanStartingAfterEndAndEndingAfterEnd() { Assert.Equal( - new[] { UnitSpan }, + [UnitSpan], UnitSpan.Subtract(TextSpan.FromBounds(RightAfterEnd(UnitSpan), RightAfterEnd(UnitSpan)))); } @@ -284,7 +283,7 @@ public void UnitSpanStartingAfterEndAndEndingAfterEnd() public void EmptySpanStartingBeforeStartAndEndingBeforeStart() { Assert.Equal( - new[] { EmptySpan }, + [EmptySpan], EmptySpan.Subtract(TextSpan.FromBounds(RightBeforeStart(EmptySpan), RightBeforeStart(EmptySpan)))); } @@ -320,7 +319,7 @@ public void EmptySpanStartingAtSpanAndEndingAfterEnd() public void EmptySpanStartingAfterEndAndEndingAfterEnd() { Assert.Equal( - new[] { EmptySpan }, + [EmptySpan], EmptySpan.Subtract(TextSpan.FromBounds(RightAfterEnd(EmptySpan), RightAfterEnd(EmptySpan)))); } } diff --git a/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs b/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs index 1956e62a97335..19f9e9853b621 100644 --- a/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs +++ b/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs @@ -113,7 +113,7 @@ static OptionSet GetOptionSetWithChangedPublicOptions(OptionSet options) var updatedOptions = options; foreach (var (option, newValue) in publicOptions) { - var languages = option.IsPerLanguage ? new[] { LanguageNames.CSharp, LanguageNames.VisualBasic } : new string?[] { null }; + var languages = option.IsPerLanguage ? [LanguageNames.CSharp, LanguageNames.VisualBasic] : new string?[] { null }; foreach (var language in languages) { diff --git a/src/Workspaces/CoreTest/SolutionTests/DocumentInfoTests.cs b/src/Workspaces/CoreTest/SolutionTests/DocumentInfoTests.cs index 0f3e9c3518ee5..0a340dcd66418 100644 --- a/src/Workspaces/CoreTest/SolutionTests/DocumentInfoTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/DocumentInfoTests.cs @@ -26,7 +26,7 @@ public void Create_Errors() Assert.Throws(() => DocumentInfo.Create(id: null, "doc")); Assert.Throws(() => DocumentInfo.Create(documentId, name: null)); - Assert.Throws(() => DocumentInfo.Create(documentId, "doc", folders: new[] { "folder", null })); + Assert.Throws(() => DocumentInfo.Create(documentId, "doc", folders: ["folder", null])); } [Fact] @@ -73,7 +73,7 @@ public void Create_Folders() { var documentId = DocumentId.CreateNewId(ProjectId.CreateNewId()); - var info1 = DocumentInfo.Create(documentId, "doc", folders: new[] { "folder" }); + var info1 = DocumentInfo.Create(documentId, "doc", folders: ["folder"]); Assert.Equal("folder", ((ImmutableArray)info1.Folders).Single()); var info2 = DocumentInfo.Create(documentId, "doc"); diff --git a/src/Workspaces/CoreTest/SolutionTests/ProjectDependencyGraphTests.cs b/src/Workspaces/CoreTest/SolutionTests/ProjectDependencyGraphTests.cs index 14cdee99f57d4..4612437cb0e79 100644 --- a/src/Workspaces/CoreTest/SolutionTests/ProjectDependencyGraphTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/ProjectDependencyGraphTests.cs @@ -227,7 +227,7 @@ public void TestTransitiveReferencesIncrementalUpdateWithProjectThatHasUnknownRe var dependencyGraph = solution.GetProjectDependencyGraph(); var projectAId = solution.GetProjectsByName("A").Single().Id; var projectBId = solution.GetProjectsByName("B").Single().Id; - dependencyGraph = dependencyGraph.WithAdditionalProjectReferences(projectAId, new[] { new ProjectReference(projectBId) }); + dependencyGraph = dependencyGraph.WithAdditionalProjectReferences(projectAId, [new ProjectReference(projectBId)]); VerifyTransitiveReferences(solution, dependencyGraph, project: "A", expectedResults: ["B"]); } @@ -246,7 +246,7 @@ public void TestTransitiveReferencesWithDanglingProjectReference() var projectBId = ProjectId.CreateNewId("B"); var projectAInfo = ProjectInfo.Create(projectAId, VersionStamp.Create(), "A", "A", LanguageNames.CSharp, - projectReferences: new[] { new ProjectReference(projectBId) }); + projectReferences: [new ProjectReference(projectBId)]); solution = solution.AddProject(projectAInfo); diff --git a/src/Workspaces/CoreTest/SolutionTests/ProjectIdTests.cs b/src/Workspaces/CoreTest/SolutionTests/ProjectIdTests.cs new file mode 100644 index 0000000000000..dfc3dc3cf4468 --- /dev/null +++ b/src/Workspaces/CoreTest/SolutionTests/ProjectIdTests.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. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.CodeAnalysis.UnitTests; + +public sealed class ProjectIdTests +{ + [Fact] + public void DebugNameNotPartOfIdentity1() + { + var guid1 = Guid.NewGuid(); + + // Same guid, so they should be considered the same, regardless of debug name. + var id1 = ProjectId.CreateFromSerialized(guid1, "debug1"); + var id2 = ProjectId.CreateFromSerialized(guid1, "debug2"); + + Assert.True(id1.Equals(id2)); + Assert.True(id1 == id2); + Assert.True(id1.GetHashCode() == id2.GetHashCode()); + Assert.True(id1.Checksum == id2.Checksum); + } + + [Fact] + public void DebugNameNotPartOfIdentity2() + { + // Different guid, so they should be considered different, regardless of debug name. + var id1 = ProjectId.CreateFromSerialized(Guid.NewGuid(), "debug1"); + var id2 = ProjectId.CreateFromSerialized(Guid.NewGuid(), "debug1"); + + Assert.False(id1.Equals(id2)); + Assert.False(id1 == id2); + Assert.False(id1.GetHashCode() == id2.GetHashCode()); + Assert.False(id1.Checksum == id2.Checksum); + } +} diff --git a/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs b/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs index 06d3ba7cdb485..30b9912cc3c94 100644 --- a/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/ProjectInfoTests.cs @@ -36,20 +36,20 @@ public void Create_Errors_DuplicateItems() var documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(pid), "doc"); Assert.Throws("documents[1]", - () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", documents: new[] { documentInfo, documentInfo })); + () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", documents: [documentInfo, documentInfo])); Assert.Throws(() => ProjectInfo.Create(pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", additionalDocuments: new DocumentInfo[] { null })); Assert.Throws("additionalDocuments[1]", - () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", additionalDocuments: new[] { documentInfo, documentInfo })); + () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", additionalDocuments: [documentInfo, documentInfo])); Assert.Throws(() => ProjectInfo.Create(pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", projectReferences: new ProjectReference[] { null })); var projectReference = new ProjectReference(ProjectId.CreateNewId()); Assert.Throws("projectReferences[1]", - () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", projectReferences: new[] { projectReference, projectReference })); + () => ProjectInfo.Create(pid, VersionStamp.Default, "proj", "assembly", "C#", projectReferences: [projectReference, projectReference])); Assert.Throws("analyzerReferences[0]", () => ProjectInfo.Create(pid, VersionStamp.Default, name: "Goo", assemblyName: "Bar", language: "C#", analyzerReferences: new AnalyzerReference[] { null })); @@ -72,7 +72,7 @@ public void Create_Documents() var version = VersionStamp.Default; var documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(ProjectId.CreateNewId()), "doc"); - var info1 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#", documents: new[] { documentInfo }); + var info1 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#", documents: [documentInfo]); Assert.Same(documentInfo, ((ImmutableArray)info1.Documents).Single()); var info2 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#"); @@ -91,7 +91,7 @@ public void Create_AdditionalDocuments() var version = VersionStamp.Default; var documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(ProjectId.CreateNewId()), "doc"); - var info1 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#", additionalDocuments: new[] { documentInfo }); + var info1 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#", additionalDocuments: [documentInfo]); Assert.Same(documentInfo, ((ImmutableArray)info1.AdditionalDocuments).Single()); var info2 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#"); @@ -110,7 +110,7 @@ public void Create_ProjectReferences() var version = VersionStamp.Default; var projectReference = new ProjectReference(ProjectId.CreateNewId()); - var info1 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#", projectReferences: new[] { projectReference }); + var info1 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#", projectReferences: [projectReference]); Assert.Same(projectReference, ((ImmutableArray)info1.ProjectReferences).Single()); var info2 = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#"); diff --git a/src/Workspaces/CoreTest/SolutionTests/SolutionInfoTests.cs b/src/Workspaces/CoreTest/SolutionTests/SolutionInfoTests.cs index 43f8a8c5712f8..b09f8b0032c11 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SolutionInfoTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SolutionInfoTests.cs @@ -21,7 +21,7 @@ public void Create_Errors() var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#"); Assert.Throws(() => SolutionInfo.Create(null, version)); - Assert.Throws(() => SolutionInfo.Create(solutionId, version, projects: new[] { projectInfo, null })); + Assert.Throws(() => SolutionInfo.Create(solutionId, version, projects: [projectInfo, null])); } [Fact] @@ -31,7 +31,7 @@ public void Create_Projects() var version = VersionStamp.Default; var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), version, "proj", "assembly", "C#"); - var info1 = SolutionInfo.Create(solutionId, version, projects: new[] { projectInfo }); + var info1 = SolutionInfo.Create(solutionId, version, projects: [projectInfo]); Assert.Same(projectInfo, ((ImmutableArray)info1.Projects).Single()); var info2 = SolutionInfo.Create(solutionId, version); diff --git a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs index 08cfdda8dfdcf..6c6a16400d9ca 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs @@ -374,11 +374,11 @@ public void WithDocumentText_MultipleDocuments() var documentId = solution.Projects.Single().DocumentIds.Single(); var text = SourceText.From("new text"); - var newSolution1 = solution.WithDocumentText(new[] { documentId }, text, PreservationMode.PreserveIdentity); + var newSolution1 = solution.WithDocumentText([documentId], text, PreservationMode.PreserveIdentity); Assert.True(newSolution1.GetDocument(documentId)!.TryGetText(out var actualText)); Assert.Same(text, actualText); - var newSolution2 = newSolution1.WithDocumentText(new[] { documentId }, text, PreservationMode.PreserveIdentity); + var newSolution2 = newSolution1.WithDocumentText([documentId], text, PreservationMode.PreserveIdentity); Assert.Same(newSolution1, newSolution2); // documents not in solution are skipped: https://github.com/dotnet/roslyn/issues/42029 @@ -386,8 +386,8 @@ public void WithDocumentText_MultipleDocuments() Assert.Same(solution, solution.WithDocumentText(new DocumentId[] { s_unrelatedDocumentId }, text)); Assert.Throws(() => solution.WithDocumentText((DocumentId[])null!, text, PreservationMode.PreserveIdentity)); - Assert.Throws(() => solution.WithDocumentText(new[] { documentId }, null!, PreservationMode.PreserveIdentity)); - Assert.Throws(() => solution.WithDocumentText(new[] { documentId }, text, (PreservationMode)(-1))); + Assert.Throws(() => solution.WithDocumentText([documentId], null!, PreservationMode.PreserveIdentity)); + Assert.Throws(() => solution.WithDocumentText([documentId], text, (PreservationMode)(-1))); } public enum TextUpdateType @@ -1365,12 +1365,12 @@ public void WithProjectReferences() var solution2 = solution.WithProjectReferences(projectId, projectRefs); Assert.Same(projectRefs, solution2.GetProject(projectId)!.AllProjectReferences); - Assert.Throws("projectId", () => solution.WithProjectReferences(null!, new[] { projectRef })); - Assert.Throws(() => solution.WithProjectReferences(ProjectId.CreateNewId(), new[] { projectRef })); + Assert.Throws("projectId", () => solution.WithProjectReferences(null!, [projectRef])); + Assert.Throws(() => solution.WithProjectReferences(ProjectId.CreateNewId(), [projectRef])); // cycles: - Assert.Throws(() => solution2.WithProjectReferences(projectId2, new[] { new ProjectReference(projectId) })); - Assert.Throws(() => solution.WithProjectReferences(projectId, new[] { new ProjectReference(projectId) })); + Assert.Throws(() => solution2.WithProjectReferences(projectId2, [new ProjectReference(projectId)])); + Assert.Throws(() => solution.WithProjectReferences(projectId, [new ProjectReference(projectId)])); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/42406")] @@ -1417,18 +1417,18 @@ public void AddProjectReferences() AssertEx.Equal(new[] { projectRef2 }, solution3.GetProject(projectId)!.ProjectReferences); AssertEx.Equal(new[] { projectRef2, externalProjectRef }, solution3.GetProject(projectId)!.AllProjectReferences); - Assert.Throws("projectId", () => solution.AddProjectReferences(null!, new[] { projectRef2 })); + Assert.Throws("projectId", () => solution.AddProjectReferences(null!, [projectRef2])); Assert.Throws("projectReferences", () => solution.AddProjectReferences(projectId, null!)); Assert.Throws("projectReferences[0]", () => solution.AddProjectReferences(projectId, new ProjectReference[] { null! })); - Assert.Throws("projectReferences[1]", () => solution.AddProjectReferences(projectId, new[] { projectRef2, projectRef2 })); - Assert.Throws("projectReferences[1]", () => solution.AddProjectReferences(projectId, new[] { new ProjectReference(projectId2), new ProjectReference(projectId2) })); + Assert.Throws("projectReferences[1]", () => solution.AddProjectReferences(projectId, [projectRef2, projectRef2])); + Assert.Throws("projectReferences[1]", () => solution.AddProjectReferences(projectId, [new ProjectReference(projectId2), new ProjectReference(projectId2)])); // dup: - Assert.Throws(() => solution.AddProjectReferences(projectId3, new[] { projectRef2 })); + Assert.Throws(() => solution.AddProjectReferences(projectId3, [projectRef2])); // cycles: - Assert.Throws(() => solution3.AddProjectReferences(projectId2, new[] { projectRef3 })); - Assert.Throws(() => solution3.AddProjectReferences(projectId, new[] { new ProjectReference(projectId) })); + Assert.Throws(() => solution3.AddProjectReferences(projectId2, [projectRef3])); + Assert.Throws(() => solution3.AddProjectReferences(projectId, [new ProjectReference(projectId)])); } [Fact] @@ -1443,7 +1443,7 @@ public void RemoveProjectReference() var projectRef2 = new ProjectReference(projectId2); var externalProjectRef = new ProjectReference(ProjectId.CreateNewId()); - solution = solution.WithProjectReferences(projectId, new[] { projectRef2, externalProjectRef }); + solution = solution.WithProjectReferences(projectId, [projectRef2, externalProjectRef]); // remove reference to a project that's not part of the solution: var solution2 = solution.RemoveProjectReference(projectId, externalProjectRef); @@ -1483,23 +1483,23 @@ public void ProjectReferences_Submissions() .AddProject(ProjectInfo.Create(submissionId2, VersionStamp.Default, name: "submission2", assemblyName: "submission2.dll", LanguageNames.CSharp, isSubmission: true)) .AddProject(ProjectInfo.Create(submissionId3, VersionStamp.Default, name: "submission3", assemblyName: "submission3.dll", LanguageNames.CSharp, isSubmission: true)) .AddProjectReference(submissionId2, new ProjectReference(submissionId1)) - .WithProjectReferences(submissionId2, new[] { new ProjectReference(submissionId1) }); + .WithProjectReferences(submissionId2, [new ProjectReference(submissionId1)]); // submission may be referenced from multiple submissions (forming a tree): - _ = solution.AddProjectReferences(submissionId3, new[] { new ProjectReference(submissionId1) }); - _ = solution.WithProjectReferences(submissionId3, new[] { new ProjectReference(submissionId1) }); + _ = solution.AddProjectReferences(submissionId3, [new ProjectReference(submissionId1)]); + _ = solution.WithProjectReferences(submissionId3, [new ProjectReference(submissionId1)]); // submission may reference a non-submission project: - _ = solution.AddProjectReferences(submissionId3, new[] { new ProjectReference(projectId0) }); - _ = solution.WithProjectReferences(submissionId3, new[] { new ProjectReference(projectId0) }); + _ = solution.AddProjectReferences(submissionId3, [new ProjectReference(projectId0)]); + _ = solution.WithProjectReferences(submissionId3, [new ProjectReference(projectId0)]); // submission can't reference multiple submissions: - Assert.Throws(() => solution.AddProjectReferences(submissionId2, new[] { new ProjectReference(submissionId3) })); - Assert.Throws(() => solution.WithProjectReferences(submissionId1, new[] { new ProjectReference(submissionId2), new ProjectReference(submissionId3) })); + Assert.Throws(() => solution.AddProjectReferences(submissionId2, [new ProjectReference(submissionId3)])); + Assert.Throws(() => solution.WithProjectReferences(submissionId1, [new ProjectReference(submissionId2), new ProjectReference(submissionId3)])); // non-submission project can't reference a submission: - Assert.Throws(() => solution.AddProjectReferences(projectId0, new[] { new ProjectReference(submissionId1) })); - Assert.Throws(() => solution.WithProjectReferences(projectId0, new[] { new ProjectReference(submissionId1) })); + Assert.Throws(() => solution.AddProjectReferences(projectId0, [new ProjectReference(submissionId1)])); + Assert.Throws(() => solution.WithProjectReferences(projectId0, [new ProjectReference(submissionId1)])); } [Fact] @@ -1516,8 +1516,8 @@ public void WithProjectMetadataReferences() metadataRef, allowDuplicates: false); - Assert.Throws("projectId", () => solution.WithProjectMetadataReferences(null!, new[] { metadataRef })); - Assert.Throws(() => solution.WithProjectMetadataReferences(ProjectId.CreateNewId(), new[] { metadataRef })); + Assert.Throws("projectId", () => solution.WithProjectMetadataReferences(null!, [metadataRef])); + Assert.Throws(() => solution.WithProjectMetadataReferences(ProjectId.CreateNewId(), [metadataRef])); } [Fact] @@ -1586,8 +1586,8 @@ public void WithProjectAnalyzerReferences() analyzerRef, allowDuplicates: false); - Assert.Throws("projectId", () => solution.WithProjectAnalyzerReferences(null!, new[] { analyzerRef })); - Assert.Throws(() => solution.WithProjectAnalyzerReferences(ProjectId.CreateNewId(), new[] { analyzerRef })); + Assert.Throws("projectId", () => solution.WithProjectAnalyzerReferences(null!, [analyzerRef])); + Assert.Throws(() => solution.WithProjectAnalyzerReferences(ProjectId.CreateNewId(), [analyzerRef])); } [Fact] @@ -2396,7 +2396,7 @@ public void TestProjectParseOptions() // Parse Options var oldParseOptions = solution.GetProject(project1).ParseOptions; - var newParseOptions = new CSharpParseOptions(preprocessorSymbols: new[] { "AFTER" }); + var newParseOptions = new CSharpParseOptions(preprocessorSymbols: ["AFTER"]); solution = solution.WithProjectParseOptions(project1, newParseOptions); var newUpdatedParseOptions = solution.GetProject(project1).ParseOptions; Assert.NotEqual(oldParseOptions, newUpdatedParseOptions); @@ -3198,11 +3198,11 @@ End Class [Fact] public void TestWorkspaceLanguageServiceOverride() { - var hostServices = FeaturesTestCompositions.Features.AddParts(new[] - { + var hostServices = FeaturesTestCompositions.Features.AddParts( + [ typeof(TestLanguageServiceA), typeof(TestLanguageServiceB), - }).GetHostServices(); + ]).GetHostServices(); var ws = new AdhocWorkspace(hostServices, ServiceLayer.Host); var service = ws.Services.GetLanguageServices(LanguageNames.CSharp).GetService(); @@ -3367,16 +3367,16 @@ public void TestEncodingRetainedAfterTreeChanged() } [Fact] - public void TestProjectWithNoMetadataReferencesHasIncompleteReferences() + public async Task TestProjectWithNoMetadataReferencesHasIncompleteReferences() { var workspace = new AdhocWorkspace(); var project = workspace.AddProject("CSharpProject", LanguageNames.CSharp); - Assert.False(project.HasSuccessfullyLoadedAsync().Result); + Assert.False(await project.HasSuccessfullyLoadedAsync(CancellationToken.None)); Assert.Empty(project.GetCompilationAsync().Result.ExternalReferences); } [Fact] - public void TestProjectWithNoBrokenReferencesHasNoIncompleteReferences() + public async Task TestProjectWithNoBrokenReferencesHasNoIncompleteReferences() { var workspace = new AdhocWorkspace(); var project1 = workspace.AddProject( @@ -3386,7 +3386,7 @@ public void TestProjectWithNoBrokenReferencesHasNoIncompleteReferences() "CSharpProject", "CSharpProject", LanguageNames.CSharp, - metadataReferences: new[] { MscorlibRef })); + metadataReferences: [MscorlibRef])); var project2 = workspace.AddProject( ProjectInfo.Create( ProjectId.CreateNewId(), @@ -3394,17 +3394,17 @@ public void TestProjectWithNoBrokenReferencesHasNoIncompleteReferences() "VisualBasicProject", "VisualBasicProject", LanguageNames.VisualBasic, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(project1.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(project1.Id)])); // Nothing should have incomplete references, and everything should build - Assert.True(project1.HasSuccessfullyLoadedAsync().Result); - Assert.True(project2.HasSuccessfullyLoadedAsync().Result); + Assert.True(await project1.HasSuccessfullyLoadedAsync(CancellationToken.None)); + Assert.True(await project2.HasSuccessfullyLoadedAsync(CancellationToken.None)); Assert.Equal(2, project2.GetCompilationAsync().Result.ExternalReferences.Length); } [Fact] - public void TestProjectWithBrokenCrossLanguageReferenceHasIncompleteReferences() + public async Task TestProjectWithBrokenCrossLanguageReferenceHasIncompleteReferences() { var workspace = new AdhocWorkspace(); var project1 = workspace.AddProject( @@ -3414,7 +3414,7 @@ public void TestProjectWithBrokenCrossLanguageReferenceHasIncompleteReferences() "CSharpProject", "CSharpProject", LanguageNames.CSharp, - metadataReferences: new[] { MscorlibRef })); + metadataReferences: [MscorlibRef])); workspace.AddDocument(project1.Id, "Broken.cs", SourceText.From("class ")); var project2 = workspace.AddProject( @@ -3424,11 +3424,11 @@ public void TestProjectWithBrokenCrossLanguageReferenceHasIncompleteReferences() "VisualBasicProject", "VisualBasicProject", LanguageNames.VisualBasic, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(project1.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(project1.Id)])); - Assert.True(project1.HasSuccessfullyLoadedAsync().Result); - Assert.False(project2.HasSuccessfullyLoadedAsync().Result); + Assert.True(await project1.HasSuccessfullyLoadedAsync(CancellationToken.None)); + Assert.False(await project2.HasSuccessfullyLoadedAsync(CancellationToken.None)); Assert.Single(project2.GetCompilationAsync().Result.ExternalReferences); } @@ -3549,7 +3549,7 @@ await documentToFreezeChanged.Project.GetSemanticVersionAsync(), } [Fact] - public void TestFrozenPartialProjectAlwaysIsIncomplete() + public async Task TestFrozenPartialProjectAlwaysIsIncomplete() { var workspace = new AdhocWorkspace(); var project1 = workspace.AddProject( @@ -3559,7 +3559,7 @@ public void TestFrozenPartialProjectAlwaysIsIncomplete() "CSharpProject", "CSharpProject", LanguageNames.CSharp, - metadataReferences: new[] { MscorlibRef })); + metadataReferences: [MscorlibRef])); var project2 = workspace.AddProject( ProjectInfo.Create( @@ -3568,16 +3568,16 @@ public void TestFrozenPartialProjectAlwaysIsIncomplete() "VisualBasicProject", "VisualBasicProject", LanguageNames.VisualBasic, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(project1.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(project1.Id)])); var document = workspace.AddDocument(project2.Id, "Test.cs", SourceText.From("")); // Nothing should have incomplete references, and everything should build var frozenSolution = document.WithFrozenPartialSemantics(CancellationToken.None).Project.Solution; - Assert.True(frozenSolution.GetProject(project1.Id).HasSuccessfullyLoadedAsync().Result); - Assert.True(frozenSolution.GetProject(project2.Id).HasSuccessfullyLoadedAsync().Result); + Assert.True(await frozenSolution.GetProject(project1.Id).HasSuccessfullyLoadedAsync(CancellationToken.None)); + Assert.True(await frozenSolution.GetProject(project2.Id).HasSuccessfullyLoadedAsync(CancellationToken.None)); } [Fact] @@ -3614,8 +3614,7 @@ public async Task TestFrozenPartialSemanticsNoCompilationYetBuilt() Assert.Same(await frozenDocument.GetSyntaxTreeAsync(), singleTree); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1467404")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1467404")] public async Task TestFrozenPartialSemanticsHandlesDocumentWithSamePathBeingRemovedAndAdded() { using var workspace = CreateWorkspaceWithPartialSemantics(); @@ -3636,8 +3635,7 @@ public async Task TestFrozenPartialSemanticsHandlesDocumentWithSamePathBeingRemo Assert.Same(await frozenDocument.GetSyntaxTreeAsync(), singleTree); } - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1467404")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1467404")] public async Task TestFrozenPartialSemanticsHandlesRemoveAndAddWithNullPathAndDifferentNames() { using var workspace = CreateWorkspaceWithPartialSemantics(); @@ -3713,29 +3711,112 @@ public async Task TestFrozenPartialSemanticsWithMulitipleUnrelatedEdits([Combina } [Fact] - public void TestProjectCompletenessWithMultipleProjects() + public async Task TestFrozenPartialSemanticsOfLinkedDocuments() + { + const int ClassDeclaration = 8855; + const int StructDeclaration = 8856; + + using var workspace = CreateWorkspaceWithPartialSemantics(); + + var contents = """ + #if X + + class C + { + } + + #else + + struct D + { + } + + #endif + """; + + // Create a normal solution with a linked doc, where each project should see a different tree for the above contents. + + var currentSolution = workspace.CurrentSolution; + var document1 = currentSolution.AddProject("TestProject1", "TestProject1", LanguageNames.CSharp) + .AddDocument("RegularDocument.cs", contents, filePath: "RegularDocument.cs"); + currentSolution = document1.Project.Solution; + + var document2 = currentSolution.AddProject("TestProject2", "TestProject2", LanguageNames.CSharp) + .AddDocument("RegularDocument.cs", contents, filePath: "RegularDocument.cs"); + currentSolution = document2.Project.Solution; + + var options = (CSharpParseOptions)document1.Project.ParseOptions; + currentSolution = currentSolution.WithProjectParseOptions(document1.Project.Id, options.WithPreprocessorSymbols("X")); + + var relatedIds1 = currentSolution.GetRelatedDocumentIds(document1.Id); + var relatedIds2 = currentSolution.GetRelatedDocumentIds(document2.Id); + AssertEx.SetEqual(relatedIds1, ImmutableArray.Create(document1.Id, document2.Id)); + AssertEx.SetEqual(relatedIds2, ImmutableArray.Create(document1.Id, document2.Id)); + + document1 = currentSolution.GetRequiredDocument(document1.Id); + document2 = currentSolution.GetRequiredDocument(document2.Id); + + var doc1Root = await document1.GetRequiredSyntaxRootAsync(CancellationToken.None); + var doc2Root = await document2.GetRequiredSyntaxRootAsync(CancellationToken.None); + + Assert.NotSame(doc1Root, doc2Root); + Assert.False(doc1Root.IsEquivalentTo(doc2Root)); + + { + // Now get the frozen version of each document. Freezing will update the siblings to have the same tree contents. + var frozenDoc1 = document1.WithFrozenPartialSemantics(CancellationToken.None); + var frozenDoc2 = frozenDoc1.Project.Solution.GetRequiredDocument(document2.Id); + + var frozenDoc1Root = await frozenDoc1.GetRequiredSyntaxRootAsync(CancellationToken.None); + var frozenDoc2Root = await frozenDoc2.GetRequiredSyntaxRootAsync(CancellationToken.None); + Assert.NotSame(frozenDoc1Root, frozenDoc2Root); + Assert.True(frozenDoc1Root.IsEquivalentTo(frozenDoc2Root)); + + // We're seeing project1's view of the file. so we should only see a class decl and no struct decl. + Assert.True(frozenDoc1Root.DescendantNodes().Any(n => n.RawKind == ClassDeclaration)); + Assert.False(frozenDoc1Root.DescendantNodes().Any(n => n.RawKind == StructDeclaration)); + } + + { + // Now get the frozen version of each document. Freezing will update the siblings to have the same tree contents. + var frozenDoc2 = document2.WithFrozenPartialSemantics(CancellationToken.None); + var frozenDoc1 = frozenDoc2.Project.Solution.GetRequiredDocument(document1.Id); + + var frozenDoc1Root = await frozenDoc1.GetRequiredSyntaxRootAsync(CancellationToken.None); + var frozenDoc2Root = await frozenDoc2.GetRequiredSyntaxRootAsync(CancellationToken.None); + Assert.NotSame(frozenDoc1Root, frozenDoc2Root); + Assert.True(frozenDoc1Root.IsEquivalentTo(frozenDoc2Root)); + + // We're seeing project2's view of the file. so we should only see a struct decl and no class decl. + Assert.False(frozenDoc1Root.DescendantNodes().Any(n => n.RawKind == ClassDeclaration)); + Assert.True(frozenDoc1Root.DescendantNodes().Any(n => n.RawKind == StructDeclaration)); + } + } + + [Fact] + public async Task TestProjectCompletenessWithMultipleProjects() { GetMultipleProjects(out var csBrokenProject, out var vbNormalProject, out var dependsOnBrokenProject, out var dependsOnVbNormalProject, out var transitivelyDependsOnBrokenProjects, out var transitivelyDependsOnNormalProjects); // check flag for a broken project itself - Assert.False(csBrokenProject.HasSuccessfullyLoadedAsync().Result); + Assert.False(await csBrokenProject.HasSuccessfullyLoadedAsync(CancellationToken.None)); // check flag for a normal project itself - Assert.True(vbNormalProject.HasSuccessfullyLoadedAsync().Result); + Assert.True(await vbNormalProject.HasSuccessfullyLoadedAsync(CancellationToken.None)); // check flag for normal project that directly reference a broken project - Assert.True(dependsOnBrokenProject.HasSuccessfullyLoadedAsync().Result); + Assert.True(await dependsOnBrokenProject.HasSuccessfullyLoadedAsync(CancellationToken.None)); // check flag for normal project that directly reference only normal project - Assert.True(dependsOnVbNormalProject.HasSuccessfullyLoadedAsync().Result); + Assert.True(await dependsOnVbNormalProject.HasSuccessfullyLoadedAsync(CancellationToken.None)); // check flag for normal project that indirectly reference a borken project // normal project -> normal project -> broken project - Assert.True(transitivelyDependsOnBrokenProjects.HasSuccessfullyLoadedAsync().Result); + Assert.True(await transitivelyDependsOnBrokenProjects.HasSuccessfullyLoadedAsync(CancellationToken.None)); // check flag for normal project that indirectly reference only normal project // normal project -> normal project -> normal project - Assert.True(transitivelyDependsOnNormalProjects.HasSuccessfullyLoadedAsync().Result); + Assert.True(await transitivelyDependsOnNormalProjects.HasSuccessfullyLoadedAsync(CancellationToken.None)); } private sealed class TestSmallFileTextLoader : FileTextLoader @@ -4126,7 +4207,7 @@ void M(C? c) [Fact] public void NoCompilationProjectsHaveNullSyntaxTreesAndSemanticModels() { - using var workspace = CreateWorkspace(new[] { typeof(NoCompilationLanguageService) }); + using var workspace = CreateWorkspace([typeof(NoCompilationLanguageService)]); var solution = workspace.CurrentSolution; var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); @@ -4147,7 +4228,7 @@ public void NoCompilationProjectsHaveNullSyntaxTreesAndSemanticModels() [Fact] public void ChangingFilePathOfFileInNoCompilationProjectWorks() { - using var workspace = CreateWorkspace(new[] { typeof(NoCompilationLanguageService) }); + using var workspace = CreateWorkspace([typeof(NoCompilationLanguageService)]); var solution = workspace.CurrentSolution; var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); @@ -4174,7 +4255,7 @@ public void AddingAndRemovingProjectsUpdatesFilePathMap() var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Default, "Test", "Test", LanguageNames.CSharp) - .WithAnalyzerConfigDocuments(new[] { DocumentInfo.Create(editorConfigDocumentId, ".editorconfig", filePath: editorConfigFilePath) }); + .WithAnalyzerConfigDocuments([DocumentInfo.Create(editorConfigDocumentId, ".editorconfig", filePath: editorConfigFilePath)]); solution = solution.AddProject(projectInfo); @@ -4202,7 +4283,7 @@ private static void GetMultipleProjects( "CSharpProject", "CSharpProject", LanguageNames.CSharp, - metadataReferences: new[] { MscorlibRef }).WithHasAllInformation(hasAllInformation: false)); + metadataReferences: [MscorlibRef]).WithHasAllInformation(hasAllInformation: false)); vbNormalProject = workspace.AddProject( ProjectInfo.Create( @@ -4211,7 +4292,7 @@ private static void GetMultipleProjects( "VisualBasicProject", "VisualBasicProject", LanguageNames.VisualBasic, - metadataReferences: new[] { MscorlibRef })); + metadataReferences: [MscorlibRef])); dependsOnBrokenProject = workspace.AddProject( ProjectInfo.Create( @@ -4220,8 +4301,8 @@ private static void GetMultipleProjects( "VisualBasicProject", "VisualBasicProject", LanguageNames.VisualBasic, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(csBrokenProject.Id), new ProjectReference(vbNormalProject.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(csBrokenProject.Id), new ProjectReference(vbNormalProject.Id)])); dependsOnVbNormalProject = workspace.AddProject( ProjectInfo.Create( @@ -4230,8 +4311,8 @@ private static void GetMultipleProjects( "CSharpProject", "CSharpProject", LanguageNames.CSharp, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(vbNormalProject.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(vbNormalProject.Id)])); transitivelyDependsOnBrokenProjects = workspace.AddProject( ProjectInfo.Create( @@ -4240,8 +4321,8 @@ private static void GetMultipleProjects( "CSharpProject", "CSharpProject", LanguageNames.CSharp, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(dependsOnBrokenProject.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(dependsOnBrokenProject.Id)])); transitivelyDependsOnNormalProjects = workspace.AddProject( ProjectInfo.Create( @@ -4250,8 +4331,8 @@ private static void GetMultipleProjects( "VisualBasicProject", "VisualBasicProject", LanguageNames.VisualBasic, - metadataReferences: new[] { MscorlibRef }, - projectReferences: new[] { new ProjectReference(dependsOnVbNormalProject.Id) })); + metadataReferences: [MscorlibRef], + projectReferences: [new ProjectReference(dependsOnVbNormalProject.Id)])); } [Fact] @@ -4303,7 +4384,7 @@ public async Task TestUpdatedDocumentTextIsObservablyConstantAsync() name: "TestProject", assemblyName: "TestProject.dll", language: LanguageNames.CSharp, - documents: new[] { docInfo }); + documents: [docInfo]); var solution = workspace.CurrentSolution.AddProject(projInfo); var doc = solution.GetDocument(docInfo.Id); diff --git a/src/Workspaces/CoreTest/SolutionTests/SolutionWithSourceGeneratorTests.cs b/src/Workspaces/CoreTest/SolutionTests/SolutionWithSourceGeneratorTests.cs index 0d3f626e6e6f4..49385353c15b6 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SolutionWithSourceGeneratorTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SolutionWithSourceGeneratorTests.cs @@ -770,7 +770,7 @@ public async Task LinkedDocumentOfFrozenShouldNotRunSourceGenerator(TestHost tes foreach (var documentIdToTest in documentIdsToTest) { var document = frozenSolution.GetRequiredDocument(documentIdToTest); - Assert.Equal(document.GetLinkedDocumentIds().Single(), documentIdsToTest.Except(new[] { documentIdToTest }).Single()); + Assert.Equal(document.GetLinkedDocumentIds().Single(), documentIdsToTest.Except([documentIdToTest]).Single()); document = document.WithText(SourceText.From("// Something else")); var compilation = await document.Project.GetRequiredCompilationAsync(CancellationToken.None); diff --git a/src/Workspaces/CoreTest/SolutionTests/SourceGeneratorTelemetryCollectorWorkspaceServiceTests.cs b/src/Workspaces/CoreTest/SolutionTests/SourceGeneratorTelemetryCollectorWorkspaceServiceTests.cs index bd166a1c57136..bb56137570ec5 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SourceGeneratorTelemetryCollectorWorkspaceServiceTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SourceGeneratorTelemetryCollectorWorkspaceServiceTests.cs @@ -20,8 +20,7 @@ namespace Microsoft.CodeAnalysis.UnitTests [UseExportProvider] public class SourceGeneratorTelemetryCollectorWorkspaceServiceTests { - [Fact] - [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1675665")] + [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1675665")] public async Task WithReferencesMethodCorrectlyUpdatesWithEqualReferences() { using var workspace = CreateWorkspace(additionalParts: [typeof(TestSourceGeneratorTelemetryCollectorWorkspaceServiceFactory)]); diff --git a/src/Workspaces/CoreTest/SolutionTests/TryApplyChangesTests.cs b/src/Workspaces/CoreTest/SolutionTests/TryApplyChangesTests.cs index 91140341134e1..63807101f0a66 100644 --- a/src/Workspaces/CoreTest/SolutionTests/TryApplyChangesTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/TryApplyChangesTests.cs @@ -121,7 +121,7 @@ public void TryApplyWorksIfAllowingAnyParseOption() Assert.True(workspace.TryApplyChanges( project.WithParseOptions( - project.ParseOptions!.WithFeatures(new[] { KeyValuePairUtil.Create("Feature", "") })).Solution)); + project.ParseOptions!.WithFeatures([KeyValuePairUtil.Create("Feature", "")])).Solution)); } [Fact] @@ -136,7 +136,7 @@ public void TryApplyWorksSpecificChangeIsAllowedForParseOption() Assert.True( workspace.TryApplyChanges( - project.WithParseOptions(project.ParseOptions!.WithFeatures(new[] { KeyValuePairUtil.Create("Feature", "ExpectedValue") })).Solution)); + project.WithParseOptions(project.ParseOptions!.WithFeatures([KeyValuePairUtil.Create("Feature", "ExpectedValue")])).Solution)); } [Fact] @@ -151,7 +151,7 @@ public void TryApplyWorksThrowsIfChangeIsDisallowedForParseOption() var exception = Assert.Throws( () => workspace.TryApplyChanges( - project.WithParseOptions(project.ParseOptions!.WithFeatures(new[] { KeyValuePairUtil.Create("Feature", "WrongThing") })).Solution)); + project.WithParseOptions(project.ParseOptions!.WithFeatures([KeyValuePairUtil.Create("Feature", "WrongThing")])).Solution)); Assert.Equal(WorkspacesResources.Changing_parse_options_is_not_supported, exception.Message); } diff --git a/src/Workspaces/CoreTest/SymbolKeyTests.cs b/src/Workspaces/CoreTest/SymbolKeyTests.cs index 962ac67875032..1aca67eaa70a3 100644 --- a/src/Workspaces/CoreTest/SymbolKeyTests.cs +++ b/src/Workspaces/CoreTest/SymbolKeyTests.cs @@ -331,7 +331,7 @@ namespace A { namespace N { } } var compilation = GetCompilation(source, LanguageNames.CSharp); var symbols = GetDeclaredSymbols(compilation); Assert.Equal(5, symbols.Count()); - Assert.Equal(new[] { "N", "A", "A.B", "A.B.C", "A.N" }, + Assert.Equal(["N", "A", "A.B", "A.B.C", "A.N"], symbols.Select(s => s.ToDisplayString())); TestRoundTrip(symbols, compilation); } @@ -1479,12 +1479,12 @@ private static Compilation GetCompilation(string source, string language, string if (language == LanguageNames.CSharp) { var tree = CSharp.SyntaxFactory.ParseSyntaxTree(source, path: path); - return CSharp.CSharpCompilation.Create("Test", syntaxTrees: new[] { tree }, references: references); + return CSharp.CSharpCompilation.Create("Test", syntaxTrees: [tree], references: references); } else if (language == LanguageNames.VisualBasic) { var tree = VisualBasic.SyntaxFactory.ParseSyntaxTree(source, path: path); - return VisualBasic.VisualBasicCompilation.Create("Test", syntaxTrees: new[] { tree }, references: references); + return VisualBasic.VisualBasicCompilation.Create("Test", syntaxTrees: [tree], references: references); } throw new NotSupportedException(); diff --git a/src/Workspaces/CoreTest/SyntaxNodeTests.cs b/src/Workspaces/CoreTest/SyntaxNodeTests.cs index 93a1ff8a5ef20..bdf2730eb9843 100644 --- a/src/Workspaces/CoreTest/SyntaxNodeTests.cs +++ b/src/Workspaces/CoreTest/SyntaxNodeTests.cs @@ -103,7 +103,7 @@ public async Task TestTrackNodesWithDocument() var cgenField = gen.FieldDeclaration("X", gen.TypeExpression(SpecialType.System_Int32), Accessibility.Private); var currentClassDecl = trackedRoot.GetCurrentNodes(classDecl).First(); - var classDeclWithField = gen.InsertMembers(currentClassDecl, 0, new[] { cgenField }); + var classDeclWithField = gen.InsertMembers(currentClassDecl, 0, [cgenField]); // we can find related bits even from sub-tree fragments var latestMethod = classDeclWithField.GetCurrentNodes(methodDecl).First(); diff --git a/src/Workspaces/CoreTest/WorkspaceTests/AdhocWorkspaceTests.cs b/src/Workspaces/CoreTest/WorkspaceTests/AdhocWorkspaceTests.cs index 2bdc2f22fd516..a4f4417560159 100644 --- a/src/Workspaces/CoreTest/WorkspaceTests/AdhocWorkspaceTests.cs +++ b/src/Workspaces/CoreTest/WorkspaceTests/AdhocWorkspaceTests.cs @@ -121,10 +121,10 @@ public void TestAddProjects() name: "TestProject2", assemblyName: "TestProject2.dll", language: LanguageNames.VisualBasic, - projectReferences: new[] { new ProjectReference(id1) }); + projectReferences: [new ProjectReference(id1)]); using var ws = new AdhocWorkspace(); - ws.AddProjects(new[] { info1, info2 }); + ws.AddProjects([info1, info2]); var solution = ws.CurrentSolution; Assert.Equal(2, solution.ProjectIds.Count); @@ -160,7 +160,7 @@ public void TestAddProject_TryApplyChanges() "NewProject", "NewProject.dll", LanguageNames.CSharp, - documents: new[] { docInfo }); + documents: [docInfo]); var newSolution = ws.CurrentSolution.AddProject(projInfo); @@ -219,7 +219,7 @@ public void TestOpenCloseDocument() name: "TestProject", assemblyName: "TestProject.dll", language: LanguageNames.CSharp, - documents: new[] { docInfo }); + documents: [docInfo]); using var ws = new AdhocWorkspace(); ws.AddProject(projInfo); @@ -253,7 +253,7 @@ public void TestOpenCloseAdditionalDocument() name: "TestProject", assemblyName: "TestProject.dll", language: LanguageNames.CSharp, - additionalDocuments: new[] { docInfo }); + additionalDocuments: [docInfo]); using var ws = new AdhocWorkspace(); ws.AddProject(projInfo); @@ -292,7 +292,7 @@ public void TestOpenCloseAnnalyzerConfigDocument() name: "TestProject", assemblyName: "TestProject.dll", language: LanguageNames.CSharp) - .WithAnalyzerConfigDocuments(new[] { docInfo }); + .WithAnalyzerConfigDocuments([docInfo]); using (var ws = new AdhocWorkspace()) { @@ -328,7 +328,7 @@ public async Task TestUpdatedDocumentHasTextVersionAsync() name: "TestProject", assemblyName: "TestProject.dll", language: LanguageNames.CSharp, - documents: new[] { docInfo }); + documents: [docInfo]); using var ws = new AdhocWorkspace(); ws.AddProject(projInfo); @@ -449,7 +449,7 @@ public async Task TestChangeDocumentFolders_TryApplyChanges() Assert.Equal(0, originalDoc.Folders.Count); - var changedDoc = originalDoc.WithFolders(new[] { "A", "B" }); + var changedDoc = originalDoc.WithFolders(["A", "B"]); Assert.Equal(2, changedDoc.Folders.Count); Assert.Equal("A", changedDoc.Folders[0]); Assert.Equal("B", changedDoc.Folders[1]); @@ -551,7 +551,7 @@ public void TestChangeDocumentInfo_TryApplyChanges() var newName = "ChangedName"; var newPath = @"\A\B\ChangedName.cs"; - var changedDoc = originalDoc.WithName(newName).WithFolders(new[] { "A", "B" }).WithFilePath(newPath); + var changedDoc = originalDoc.WithName(newName).WithFolders(["A", "B"]).WithFilePath(newPath); Assert.Equal(newName, changedDoc.Name); Assert.Equal(2, changedDoc.Folders.Count); @@ -578,8 +578,7 @@ public void TestDefaultDocumentTextDifferencingService() Assert.Equal(typeof(DefaultDocumentTextDifferencingService), service.GetType()); } - [Fact] - [WorkItem("https://github.com/dotnet/roslyn/pull/67142")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/pull/67142")] public void TestNotGCRootedOnConstruction() { var composition = FeaturesTestCompositions.Features; diff --git a/src/Workspaces/CoreTest/WorkspaceTests/DynamicFileInfoProviderMefTests.cs b/src/Workspaces/CoreTest/WorkspaceTests/DynamicFileInfoProviderMefTests.cs index 27436a749d47a..47ebc52769afa 100644 --- a/src/Workspaces/CoreTest/WorkspaceTests/DynamicFileInfoProviderMefTests.cs +++ b/src/Workspaces/CoreTest/WorkspaceTests/DynamicFileInfoProviderMefTests.cs @@ -23,7 +23,7 @@ public void TestFileExtensionsMetadata() var lazy = GetDynamicFileInfoProvider(); Assert.Equal(2, lazy.Metadata.Extensions.Count()); - AssertEx.SetEqual(new[] { "cshtml", "vbhtml" }, lazy.Metadata.Extensions); + AssertEx.SetEqual(["cshtml", "vbhtml"], lazy.Metadata.Extensions); } [Fact] diff --git a/src/Workspaces/CoreTest/WorkspaceTests/WorkspaceTests.cs b/src/Workspaces/CoreTest/WorkspaceTests/WorkspaceTests.cs index d8cdf07c850ab..84b367ddbe267 100644 --- a/src/Workspaces/CoreTest/WorkspaceTests/WorkspaceTests.cs +++ b/src/Workspaces/CoreTest/WorkspaceTests/WorkspaceTests.cs @@ -58,7 +58,7 @@ public void TestChangeDocumentFolders_TryApplyChanges_Throws() Assert.Equal(0, originalDoc.Folders.Count); - var changedDoc = originalDoc.WithFolders(new[] { "A", "B" }); + var changedDoc = originalDoc.WithFolders(["A", "B"]); Assert.Equal(2, changedDoc.Folders.Count); Assert.Equal("A", changedDoc.Folders[0]); Assert.Equal("B", changedDoc.Folders[1]); diff --git a/src/Workspaces/CoreTestUtilities/Fakes/SimpleAssetSource.cs b/src/Workspaces/CoreTestUtilities/Fakes/SimpleAssetSource.cs index ee48433cd9276..5f4e31d523c6e 100644 --- a/src/Workspaces/CoreTestUtilities/Fakes/SimpleAssetSource.cs +++ b/src/Workspaces/CoreTestUtilities/Fakes/SimpleAssetSource.cs @@ -36,7 +36,7 @@ public ValueTask> GetAssetsAsync( stream.Position = 0; using var reader = ObjectReader.GetReader(stream, leaveOpen: true, cancellationToken); - var asset = deserializerService.Deserialize(data.GetWellKnownSynchronizationKind(), reader, cancellationToken); + var asset = deserializerService.Deserialize(data.GetWellKnownSynchronizationKind(), reader, cancellationToken); Contract.ThrowIfNull(asset); results.Add(asset); } diff --git a/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs b/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs index 3751a2c995f9e..84c250d2915d1 100644 --- a/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs +++ b/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs @@ -28,7 +28,7 @@ private protected Task AssertFormatAsync( OptionsCollection? changedOptionSet = null, bool testWithTransformation = true) { - return AssertFormatAsync(expected, code, new[] { new TextSpan(0, code.Length) }, language, debugMode, changedOptionSet, testWithTransformation); + return AssertFormatAsync(expected, code, [new TextSpan(0, code.Length)], language, debugMode, changedOptionSet, testWithTransformation); } private protected async Task AssertFormatAsync( diff --git a/src/Workspaces/CoreTestUtilities/Options/OptionsTestHelpers.cs b/src/Workspaces/CoreTestUtilities/Options/OptionsTestHelpers.cs index 686ec03e9a7cc..f55e4ea4700de 100644 --- a/src/Workspaces/CoreTestUtilities/Options/OptionsTestHelpers.cs +++ b/src/Workspaces/CoreTestUtilities/Options/OptionsTestHelpers.cs @@ -113,7 +113,7 @@ public static OptionSet GetOptionSetWithChangedOptions(OptionSet options, IEnume } public static IEnumerable GetApplicableLanguages(IOption option) - => option.IsPerLanguage ? new[] { LanguageNames.CSharp, LanguageNames.VisualBasic } : new string?[] { null }; + => option.IsPerLanguage ? [LanguageNames.CSharp, LanguageNames.VisualBasic] : [null]; public static object? GetDifferentValue(Type type, object? value) => value switch diff --git a/src/Workspaces/MSBuildTest/RpcTests.cs b/src/Workspaces/MSBuildTest/RpcTests.cs index 93cce6935b71d..1a0ccee7070ee 100644 --- a/src/Workspaces/MSBuildTest/RpcTests.cs +++ b/src/Workspaces/MSBuildTest/RpcTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.MSBuild.Rpc; +using Microsoft.VisualStudio.Telemetry; using Nerdbank.Streams; using Xunit; @@ -190,6 +191,20 @@ public async Task ExceptionHandling() Assert.Contains("Exception thrown by test method!", exception.Message); } + [Fact] + public async Task CancelledTaskDoesNotLeakRequest() + { + await using var rpcPair = new RpcPair(); + + var tokenSource = new CancellationTokenSource(); + tokenSource.Cancel(); + + rpcPair.Server.AddTarget(new ObjectWithHelloMethod()); + await Assert.ThrowsAnyAsync(async () => await rpcPair.Client.InvokeAsync(targetObject: 0, nameof(ObjectWithHelloMethod.Hello), [], tokenSource.Token)); + + Assert.Equal(0, rpcPair.Client.GetTestAccessor().GetOutstandingRequestCount()); + } + #pragma warning disable CA1822 // Mark members as static private sealed class ObjectWithHelloMethod { public string Hello(string name) { return "Hello " + name; } } diff --git a/src/Workspaces/MSBuildTest/VisualStudioMSBuildWorkspaceTests.cs b/src/Workspaces/MSBuildTest/VisualStudioMSBuildWorkspaceTests.cs index d81278c7f4d88..7322ab7cc65c5 100644 --- a/src/Workspaces/MSBuildTest/VisualStudioMSBuildWorkspaceTests.cs +++ b/src/Workspaces/MSBuildTest/VisualStudioMSBuildWorkspaceTests.cs @@ -90,6 +90,20 @@ public async Task TestOpenSolution_MultiProjectSolution() Assert.Equal(5, compReferences.Count); } + [ConditionalFact(typeof(VisualStudioMSBuildInstalled))] + public async Task TestDirectUseOfMSBuildProjectLoader() + { + CreateFiles(GetSimpleCSharpSolutionFiles()); + var solutionFilePath = GetSolutionFileName("TestSolution.sln"); + + using var workspace = CreateMSBuildWorkspace(); + var msbuildProjectLoader = new MSBuildProjectLoader(workspace); + var solutionInfo = await msbuildProjectLoader.LoadSolutionInfoAsync(solutionFilePath); + var projectInfo = Assert.Single(solutionInfo.Projects); + + Assert.Single(projectInfo.Documents.Where(d => d.Name == "CSharpClass.cs")); + } + [ConditionalFact(typeof(VisualStudioMSBuildInstalled))] public async Task Test_SharedMetadataReferences() { @@ -2349,18 +2363,18 @@ public async Task TestLoadTextSync() CreateFiles(files); - using var workspace = new AdhocWorkspace(MSBuildMefHostServices.DefaultServices, WorkspaceKind.MSBuild); + using var workspace = CreateMSBuildWorkspace(); var projectFullPath = GetSolutionFileName(@"AnalyzerSolution\CSharpProject_AnalyzerReference.csproj"); - var loader = new MSBuildProjectLoader(workspace); - var infos = await loader.LoadProjectInfoAsync(projectFullPath); + var project = await workspace.OpenProjectAsync(projectFullPath); - var doc = infos[0].Documents[0]; - var tav = doc.TextLoader.LoadTextAndVersionSynchronously(new LoadTextOptions(SourceHashAlgorithms.Default), CancellationToken.None); + var document = project.Documents.Single(d => d.Name == "CSharpClass.cs"); + var documentText = document.GetTextSynchronously(CancellationToken.None); + Assert.Contains("public class CSharpClass", documentText.ToString(), StringComparison.Ordinal); - var adoc = infos[0].AdditionalDocuments.First(a => a.Name == "XamlFile.xaml"); - var atav = adoc.TextLoader.LoadTextAndVersionSynchronously(new LoadTextOptions(SourceHashAlgorithms.Default), CancellationToken.None); - Assert.Contains("Window", atav.Text.ToString(), StringComparison.Ordinal); + var additionalDocument = project.AdditionalDocuments.Single(a => a.Name == "XamlFile.xaml"); + var additionalDocumentText = additionalDocument.GetTextSynchronously(CancellationToken.None); + Assert.Contains("Window", additionalDocumentText.ToString(), StringComparison.Ordinal); } [ConditionalFact(typeof(VisualStudioMSBuildInstalled))] @@ -3290,7 +3304,7 @@ public async Task MSBuildWorkspaceDocumentsFoldersProperty() using var workspace = CreateMSBuildWorkspace(); var project = await workspace.OpenProjectAsync(GetSolutionFileName("Project.csproj")); var document = project.Documents.Single(d => d.Name == "MyClass.cs"); - Assert.Equal(new[] { "dir1", "dir2", "dir3" }, document.Folders); + Assert.Equal(["dir1", "dir2", "dir3"], document.Folders); } [ConditionalFact(typeof(VisualStudioMSBuildInstalled))] @@ -3303,7 +3317,7 @@ public async Task MSBuildWorkspaceLinkedDocumentHasFolders() using var workspace = CreateMSBuildWorkspace(); var project = await workspace.OpenProjectAsync(GetSolutionFileName(@"CSharpProject\CSharpProject.csproj")); var linkedDocument = project.Documents.Single(d => d.Name == "Foo.cs"); - Assert.Equal(new[] { "Blah" }, linkedDocument.Folders); + Assert.Equal(["Blah"], linkedDocument.Folders); } [ConditionalFact(typeof(VisualStudioMSBuildInstalled))] @@ -3316,7 +3330,7 @@ public async Task MSBuildWorkspaceWithDocumentInParentFolders() using var workspace = CreateMSBuildWorkspace(); var project = await workspace.OpenProjectAsync(GetSolutionFileName(@"CSharpProject\CSharpProject.csproj")); var linkedDocument = project.Documents.Single(d => d.Name == "MyClass.cs"); - Assert.Equal(new[] { "..", "MyDir" }, linkedDocument.Folders); + Assert.Equal(["..", "MyDir"], linkedDocument.Folders); } private class InMemoryAssemblyLoader : IAnalyzerAssemblyLoader diff --git a/src/Workspaces/Remote/Core/AbstractAssetProvider.cs b/src/Workspaces/Remote/Core/AbstractAssetProvider.cs index 2f407e2887a3d..74e9dc72f68ed 100644 --- a/src/Workspaces/Remote/Core/AbstractAssetProvider.cs +++ b/src/Workspaces/Remote/Core/AbstractAssetProvider.cs @@ -31,7 +31,7 @@ public async Task CreateSolutionInfoAsync(Checksum solutionChecksu using var _ = ArrayBuilder.GetInstance(solutionChecksums.Projects.Length, out var projects); foreach (var (projectChecksum, projectId) in solutionChecksums.Projects) - projects.AddIfNotNull(await CreateProjectInfoAsync(projectId, projectChecksum, cancellationToken).ConfigureAwait(false)); + projects.Add(await CreateProjectInfoAsync(projectId, projectChecksum, cancellationToken).ConfigureAwait(false)); var analyzerReferences = await CreateCollectionAsync(AssetHint.None, solutionChecksums.AnalyzerReferences, cancellationToken).ConfigureAwait(false); @@ -39,18 +39,13 @@ public async Task CreateSolutionInfoAsync(Checksum solutionChecksu solutionAttributes.Id, solutionAttributes.Version, solutionAttributes.FilePath, projects.ToImmutableAndClear(), analyzerReferences).WithTelemetryId(solutionAttributes.TelemetryId); } - public async Task CreateProjectInfoAsync(ProjectId projectId, Checksum projectChecksum, CancellationToken cancellationToken) + public async Task CreateProjectInfoAsync(ProjectId projectId, Checksum projectChecksum, CancellationToken cancellationToken) { var projectChecksums = await GetAssetAsync(assetHint: projectId, projectChecksum, cancellationToken).ConfigureAwait(false); Contract.ThrowIfFalse(projectId == projectChecksums.ProjectId); var attributes = await GetAssetAsync(assetHint: projectId, projectChecksums.Info, cancellationToken).ConfigureAwait(false); - if (!RemoteSupportedLanguages.IsSupported(attributes.Language)) - { - // only add project our workspace supports. - // workspace doesn't allow creating project with unknown languages - return null; - } + Contract.ThrowIfFalse(RemoteSupportedLanguages.IsSupported(attributes.Language)); var compilationOptions = attributes.FixUpCompilationOptions( await GetAssetAsync(assetHint: projectId, projectChecksums.CompilationOptions, cancellationToken).ConfigureAwait(false)); diff --git a/src/Workspaces/Remote/Core/RemoteHostAssetSerialization.cs b/src/Workspaces/Remote/Core/RemoteHostAssetSerialization.cs index 5dba1160a09ad..770150e2d5ea1 100644 --- a/src/Workspaces/Remote/Core/RemoteHostAssetSerialization.cs +++ b/src/Workspaces/Remote/Core/RemoteHostAssetSerialization.cs @@ -100,7 +100,7 @@ public static ImmutableArray ReadData(Stream stream, Checksum solutionCh var kind = (WellKnownSynchronizationKind)reader.ReadInt32(); // in service hub, cancellation means simply closed stream - var result = serializerService.Deserialize(kind, reader, cancellationToken); + var result = serializerService.Deserialize(kind, reader, cancellationToken); Contract.ThrowIfNull(result); results.Add(result); } diff --git a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf index 262f3c188cab9..a6dab4774b523 100644 --- a/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf +++ b/src/Workspaces/Remote/Core/xlf/RemoteWorkspacesResources.pt-BR.xlf @@ -134,7 +134,7 @@ Source generation - Geração de origem + Geração de fontes diff --git a/src/Workspaces/Remote/ServiceHub/Host/AssetProvider.cs b/src/Workspaces/Remote/ServiceHub/Host/AssetProvider.cs index 06b4bf0f5a2e4..4c0fe1193a253 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/AssetProvider.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/AssetProvider.cs @@ -40,8 +40,7 @@ public override async ValueTask GetAssetAsync( if (_assetCache.TryGetAsset(checksum, out var asset)) return asset; - using var pooledObject = SharedPools.Default>().GetPooledObject(); - var checksums = pooledObject.Object; + using var _ = PooledHashSet.GetInstance(out var checksums); checksums.Add(checksum); await this.SynchronizeAssetsAsync(assetHint, checksums, cancellationToken).ConfigureAwait(false); diff --git a/src/Workspaces/Remote/ServiceHub/Host/ChecksumSynchronizer.cs b/src/Workspaces/Remote/ServiceHub/Host/ChecksumSynchronizer.cs index 915361bc38661..420d033463e1b 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/ChecksumSynchronizer.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/ChecksumSynchronizer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Serialization; using Roslyn.Utilities; @@ -42,8 +43,7 @@ public async ValueTask SynchronizeSolutionAssetsAsync(Checksum solutionChecksum, // second, get direct children of the solution { - using var pooledObject = SharedPools.Default>().GetPooledObject(); - var checksums = pooledObject.Object; + using var _ = PooledHashSet.GetInstance(out var checksums); solutionChecksumObject.AddAllTo(checksums); checksums.Remove(solutionChecksumObject.Checksum); @@ -70,8 +70,7 @@ public async ValueTask SynchronizeProjectAssetsAsync(ProjectStateChecksums proje private async ValueTask SynchronizeProjectAssets_NoLockAsync(ProjectStateChecksums projectChecksum, CancellationToken cancellationToken) { // get children of project checksum objects at once - using var pooledObject = SharedPools.Default>().GetPooledObject(); - var checksums = pooledObject.Object; + using var _ = PooledHashSet.GetInstance(out var checksums); checksums.Add(projectChecksum.Info); checksums.Add(projectChecksum.CompilationOptions); diff --git a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.SolutionCreator.cs b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.SolutionCreator.cs index dcea83085c553..05f52bb877b48 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.SolutionCreator.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.SolutionCreator.cs @@ -2,6 +2,7 @@ // 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.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -9,15 +10,12 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Serialization; -using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; -using System; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Serialization; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote { @@ -101,7 +99,7 @@ public async Task CreateSolutionAsync(Checksum newSolutionChecksum, Ca #if DEBUG // make sure created solution has same checksum as given one - await ValidateChecksumAsync(newSolutionChecksum, solution, cancellationToken).ConfigureAwait(false); + await ValidateChecksumAsync(newSolutionChecksum, solution, newSolutionChecksums.ProjectConeId, cancellationToken).ConfigureAwait(false); #endif return solution; @@ -115,112 +113,150 @@ public async Task CreateSolutionAsync(Checksum newSolutionChecksum, Ca private async Task UpdateProjectsAsync( Solution solution, SolutionStateChecksums oldSolutionChecksums, SolutionStateChecksums newSolutionChecksums, CancellationToken cancellationToken) { - using var olds = SharedPools.Default>().GetPooledObject(); - using var news = SharedPools.Default>().GetPooledObject(); + var solutionState = solution.SolutionState; + + using var _1 = PooledDictionary.GetInstance(out var oldProjectIdToChecksum); + using var _2 = PooledDictionary.GetInstance(out var newProjectIdToChecksum); + using var _3 = PooledHashSet.GetInstance(out var allProjectIds); + + foreach (var (oldChecksum, projectId) in oldSolutionChecksums.Projects) + oldProjectIdToChecksum.Add(projectId, oldChecksum); + + foreach (var (newChecksum, projectId) in newSolutionChecksums.Projects) + newProjectIdToChecksum.Add(projectId, newChecksum); + + allProjectIds.AddRange(oldSolutionChecksums.Projects.Ids); + allProjectIds.AddRange(newSolutionChecksums.Projects.Ids); + + // If there are old projects that are now missing on the new side, and this is a projectConeSync, then + // exclude them from the old side as well. This way we only consider projects actually added or + // changed. + // + // Importantly, this means in the event of a cone-sync, we never drop projects locally. That's very + // desirable as it will likely be useful in future calls to still know about that project info without + // it being dropped and having to be resynced. + var isConeSync = newSolutionChecksums.ProjectConeId != null; + if (isConeSync) + { + foreach (var (oldChecksum, oldProjectId) in oldSolutionChecksums.Projects) + { + if (!newProjectIdToChecksum.ContainsKey(oldProjectId)) + oldProjectIdToChecksum.Remove(oldProjectId); + } - olds.Object.UnionWith(oldSolutionChecksums.Projects.Checksums); - news.Object.UnionWith(newSolutionChecksums.Projects.Checksums); + // All the old projects must be in the new project set. Though the reverse doesn't have to hold. + // The new project set may contain additional projects to add. + Contract.ThrowIfFalse(oldProjectIdToChecksum.Keys.All(newProjectIdToChecksum.Keys.Contains)); + } + + // remove projects that are the same on both sides. + foreach (var projectId in allProjectIds) + { + if (oldProjectIdToChecksum.TryGetValue(projectId, out var oldChecksum) && + newProjectIdToChecksum.TryGetValue(projectId, out var newChecksum) && + oldChecksum == newChecksum) + { + oldProjectIdToChecksum.Remove(projectId); + newProjectIdToChecksum.Remove(projectId); + } + } + + using var _4 = PooledDictionary.GetInstance(out var oldProjectIdToStateChecksums); + using var _5 = PooledDictionary.GetInstance(out var newProjectIdToStateChecksums); + + foreach (var (projectId, oldChecksum) in oldProjectIdToChecksum) + { + var oldProjectState = solutionState.GetRequiredProjectState(projectId); + + // this should be cheap since we already computed oldSolutionChecksums (which calls into this). + var oldProjectStateChecksums = await oldProjectState.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false); + Contract.ThrowIfTrue(oldProjectStateChecksums.ProjectId != projectId); + Contract.ThrowIfTrue(oldChecksum != oldProjectStateChecksums.Checksum); + + oldProjectIdToStateChecksums.Add(projectId, oldProjectStateChecksums); + } - // remove projects that exist in both side - olds.Object.ExceptWith(newSolutionChecksums.Projects.Checksums); - news.Object.ExceptWith(oldSolutionChecksums.Projects.Checksums); + // sync over the *info* about all the added/changed projects. We'll want the info so we can determine + // what actually changed. + using var _6 = PooledHashSet.GetInstance(out var newChecksumsToSync); + newChecksumsToSync.AddRange(newProjectIdToChecksum.Values); - using var _1 = PooledDictionary.GetInstance(out var oldMap); - using var _2 = PooledDictionary.GetInstance(out var newMap); + var newProjectStateChecksums = await _assetProvider.GetAssetsAsync( + assetHint: AssetHint.None, newChecksumsToSync, cancellationToken).ConfigureAwait(false); - await PopulateOldProjectMapAsync().ConfigureAwait(false); - await PopulateNewProjectMapAsync(this).ConfigureAwait(false); + foreach (var (checksum, newProjectStateChecksum) in newProjectStateChecksums) + { + Contract.ThrowIfTrue(checksum != newProjectStateChecksum.Checksum); + newProjectIdToStateChecksums.Add(newProjectStateChecksum.ProjectId, newProjectStateChecksum); + } - // bulk sync assets - await SynchronizeAssetsAsync(oldMap, newMap, cancellationToken).ConfigureAwait(false); + // Now that we've collected the old and new project state checksums, we can actually process them to + // determine what to remove, what to add, and what to change. + solution = await UpdateProjectsAsync( + solution, isConeSync, oldProjectIdToStateChecksums, newProjectIdToStateChecksums, cancellationToken).ConfigureAwait(false); + + return solution; + } + private async Task UpdateProjectsAsync( + Solution solution, + bool isConeSync, + Dictionary oldProjectIdToStateChecksums, + Dictionary newProjectIdToStateChecksums, + CancellationToken cancellationToken) + { // added project - foreach (var (projectId, newProjectChecksums) in newMap) + foreach (var (projectId, newProjectChecksums) in newProjectIdToStateChecksums) { - if (!oldMap.ContainsKey(projectId)) + if (!oldProjectIdToStateChecksums.ContainsKey(projectId)) { - var projectInfo = await _assetProvider.CreateProjectInfoAsync(projectId, newProjectChecksums.Checksum, cancellationToken).ConfigureAwait(false); - if (projectInfo == null) - { - // this project is not supported in OOP - continue; - } + // bulk sync added project assets fully since we'll definitely need that data, and we won't want + // to make tons of intermediary calls for it. - // we have new project added + await _assetProvider.SynchronizeProjectAssetsAsync(newProjectChecksums, cancellationToken).ConfigureAwait(false); + var projectInfo = await _assetProvider.CreateProjectInfoAsync(projectId, newProjectChecksums.Checksum, cancellationToken).ConfigureAwait(false); solution = solution.AddProject(projectInfo); } } // remove all project references from projects that changed. this ensures exceptions will not occur for // cyclic references during an incremental update. - foreach (var (projectId, newProjectChecksums) in newMap) + foreach (var (projectId, newProjectChecksums) in newProjectIdToStateChecksums) { - if (!oldMap.TryGetValue(projectId, out var oldProjectChecksums)) - { - continue; - } - - if (oldProjectChecksums.ProjectReferences.Checksum != newProjectChecksums.ProjectReferences.Checksum) + // Only have to do something if this was a changed project, and specifically the project references + // changed. + if (oldProjectIdToStateChecksums.TryGetValue(projectId, out var oldProjectChecksums) && + oldProjectChecksums.ProjectReferences.Checksum != newProjectChecksums.ProjectReferences.Checksum) { solution = solution.WithProjectReferences(projectId, SpecializedCollections.EmptyEnumerable()); } } // removed project - foreach (var (projectId, _) in oldMap) + foreach (var (projectId, _) in oldProjectIdToStateChecksums) { - if (!newMap.ContainsKey(projectId)) + if (!newProjectIdToStateChecksums.ContainsKey(projectId)) { - // we have a project removed + // Should never be removing projects during cone syncing. + Contract.ThrowIfTrue(isConeSync); solution = solution.RemoveProject(projectId); } } // changed project - foreach (var (projectId, newProjectChecksums) in newMap) + foreach (var (projectId, newProjectChecksums) in newProjectIdToStateChecksums) { - if (!oldMap.TryGetValue(projectId, out var oldProjectChecksums)) + if (oldProjectIdToStateChecksums.TryGetValue(projectId, out var oldProjectChecksums)) { - continue; + // If this project was in the old map, then the project must have changed. Otherwise, we would + // have removed it earlier on. + Contract.ThrowIfTrue(oldProjectChecksums.Checksum == newProjectChecksums.Checksum); + solution = await UpdateProjectAsync( + solution.GetRequiredProject(projectId), oldProjectChecksums, newProjectChecksums, cancellationToken).ConfigureAwait(false); } - - Contract.ThrowIfTrue(oldProjectChecksums.Checksum == newProjectChecksums.Checksum); - - solution = await UpdateProjectAsync(solution.GetRequiredProject(projectId), oldProjectChecksums, newProjectChecksums, cancellationToken).ConfigureAwait(false); } return solution; - - async Task PopulateOldProjectMapAsync() - { - foreach (var (projectId, projectState) in solution.SolutionState.ProjectStates) - { - var projectChecksums = await projectState.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false); - if (olds.Object.Contains(projectChecksums.Checksum)) - oldMap.Add(projectId, projectChecksums); - } - } - - async Task PopulateNewProjectMapAsync(SolutionCreator @this) - { - var projectStateChecksums = await @this._assetProvider.GetAssetsAsync( - assetHint: AssetHint.None, news.Object, cancellationToken).ConfigureAwait(false); - - foreach (var (_, projectStateChecksum) in projectStateChecksums) - newMap.Add(projectStateChecksum.ProjectId, projectStateChecksum); - } - } - - private async ValueTask SynchronizeAssetsAsync(Dictionary oldMap, Dictionary newMap, CancellationToken cancellationToken) - { - // added project - foreach (var (projectId, projectStateChecksums) in newMap) - { - if (oldMap.ContainsKey(projectId)) - continue; - - await _assetProvider.SynchronizeProjectAssetsAsync(projectStateChecksums, cancellationToken).ConfigureAwait(false); - } } private async Task UpdateProjectAsync(Project project, ProjectStateChecksums oldProjectChecksums, ProjectStateChecksums newProjectChecksums, CancellationToken cancellationToken) @@ -388,18 +424,18 @@ private async Task UpdateDocumentsAsync( Func, Solution> removeDocuments, CancellationToken cancellationToken) where TDocumentState : TextDocumentState { - using var olds = SharedPools.Default>().GetPooledObject(); - using var news = SharedPools.Default>().GetPooledObject(); + using var _1 = PooledHashSet.GetInstance(out var olds); + using var _2 = PooledHashSet.GetInstance(out var news); - olds.Object.UnionWith(oldChecksums.Checksums); - news.Object.UnionWith(newChecksums.Checksums); + olds.AddRange(oldChecksums.Checksums.Children); + news.AddRange(newChecksums.Checksums.Children); // remove documents that exist in both side - olds.Object.ExceptWith(newChecksums.Checksums); - news.Object.ExceptWith(oldChecksums.Checksums); + olds.ExceptWith(newChecksums.Checksums); + news.ExceptWith(oldChecksums.Checksums); - using var _1 = PooledDictionary.GetInstance(out var oldMap); - using var _2 = PooledDictionary.GetInstance(out var newMap); + using var _3 = PooledDictionary.GetInstance(out var oldDocumentIdToStateChecksums); + using var _4 = PooledDictionary.GetInstance(out var newDocumentIdToStateChecksums); await PopulateOldDocumentMapAsync().ConfigureAwait(false); await PopulateNewDocumentMapAsync(this).ConfigureAwait(false); @@ -407,16 +443,16 @@ private async Task UpdateDocumentsAsync( // If more than two documents changed during a single update, perform a bulk synchronization on the // project to avoid large numbers of small synchronization calls during document updates. // 🔗 https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1365014 - if (newMap.Count > 2) + if (newDocumentIdToStateChecksums.Count > 2) { await _assetProvider.SynchronizeProjectAssetsAsync(projectChecksums, cancellationToken).ConfigureAwait(false); } // added document ImmutableArray.Builder? lazyDocumentsToAdd = null; - foreach (var (documentId, newDocumentChecksums) in newMap) + foreach (var (documentId, newDocumentChecksums) in newDocumentIdToStateChecksums) { - if (!oldMap.ContainsKey(documentId)) + if (!oldDocumentIdToStateChecksums.ContainsKey(documentId)) { lazyDocumentsToAdd ??= ImmutableArray.CreateBuilder(); @@ -433,9 +469,9 @@ private async Task UpdateDocumentsAsync( } // changed document - foreach (var (documentId, newDocumentChecksums) in newMap) + foreach (var (documentId, newDocumentChecksums) in newDocumentIdToStateChecksums) { - if (!oldMap.TryGetValue(documentId, out var oldDocumentChecksums)) + if (!oldDocumentIdToStateChecksums.TryGetValue(documentId, out var oldDocumentChecksums)) { continue; } @@ -450,9 +486,9 @@ private async Task UpdateDocumentsAsync( // removed document ImmutableArray.Builder? lazyDocumentsToRemove = null; - foreach (var (documentId, _) in oldMap) + foreach (var (documentId, _) in oldDocumentIdToStateChecksums) { - if (!newMap.ContainsKey(documentId)) + if (!newDocumentIdToStateChecksums.ContainsKey(documentId)) { // we have a document removed lazyDocumentsToRemove ??= ImmutableArray.CreateBuilder(); @@ -472,18 +508,18 @@ async Task PopulateOldDocumentMapAsync() foreach (var (_, state) in existingTextDocumentStates.States) { var documentChecksums = await state.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false); - if (olds.Object.Contains(documentChecksums.Checksum)) - oldMap.Add(state.Id, documentChecksums); + if (olds.Contains(documentChecksums.Checksum)) + oldDocumentIdToStateChecksums.Add(state.Id, documentChecksums); } } async Task PopulateNewDocumentMapAsync(SolutionCreator @this) { var documentStateChecksums = await @this._assetProvider.GetAssetsAsync( - assetHint: project.Id, news.Object, cancellationToken).ConfigureAwait(false); + assetHint: project.Id, news, cancellationToken).ConfigureAwait(false); foreach (var (_, documentStateChecksum) in documentStateChecksums) - newMap.Add(documentStateChecksum.DocumentId, documentStateChecksum); + newDocumentIdToStateChecksums.Add(documentStateChecksum.DocumentId, documentStateChecksum); } } @@ -544,13 +580,24 @@ private async Task UpdateDocumentInfoAsync(TextDocument document, } #if DEBUG - private async Task ValidateChecksumAsync(Checksum checksumFromRequest, Solution incrementalSolutionBuilt, CancellationToken cancellationToken) + private async Task ValidateChecksumAsync( + Checksum checksumFromRequest, + Solution incrementalSolutionBuilt, + ProjectId? projectConeId, + CancellationToken cancellationToken) { - var currentSolutionChecksum = await incrementalSolutionBuilt.CompilationState.GetChecksumAsync(CancellationToken.None).ConfigureAwait(false); + // In the case of a cone sync, we only want to compare the checksum of the cone sync'ed over to the + // current checksum of that same cone. What is outside of those cones is totally allowed to be + // different. + // + // Note: this is acceptable because that's the contract of a cone sync. Features themselves are not + // allowed to cone-sync and then do anything that needs host/remote invariants outside of that cone. + var currentSolutionChecksum = projectConeId == null + ? await incrementalSolutionBuilt.CompilationState.GetChecksumAsync(cancellationToken).ConfigureAwait(false) + : await incrementalSolutionBuilt.CompilationState.GetChecksumAsync(projectConeId, cancellationToken).ConfigureAwait(false); + if (checksumFromRequest == currentSolutionChecksum) - { return; - } var solutionInfo = await _assetProvider.CreateSolutionInfoAsync(checksumFromRequest, cancellationToken).ConfigureAwait(false); var workspace = new AdhocWorkspace(_hostServices); diff --git a/src/Workspaces/Remote/ServiceHub/Host/Storage/RemoteCloudCachePersistentStorageService.cs b/src/Workspaces/Remote/ServiceHub/Host/Storage/RemoteCloudCachePersistentStorageService.cs deleted file mode 100644 index 369589e98a6af..0000000000000 --- a/src/Workspaces/Remote/ServiceHub/Host/Storage/RemoteCloudCachePersistentStorageService.cs +++ /dev/null @@ -1,67 +0,0 @@ -// 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. - -using System; -using System.Collections.Immutable; -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Remote.Host; -using Microsoft.CodeAnalysis.Storage.CloudCache; -using Microsoft.ServiceHub.Framework; -using Microsoft.VisualStudio; -using Microsoft.VisualStudio.LanguageServices.Storage; -using Microsoft.VisualStudio.RpcContracts.Caching; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.Remote.Storage -{ - internal class RemoteCloudCachePersistentStorageService : AbstractCloudCachePersistentStorageService - { - [ExportWorkspaceServiceFactory(typeof(ICloudCacheStorageService), WorkspaceKind.RemoteWorkspace), Shared] - internal class ServiceFactory : IWorkspaceServiceFactory - { - private readonly IGlobalServiceBroker _globalServiceBroker; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ServiceFactory(IGlobalServiceBroker globalServiceBroker) - { - _globalServiceBroker = globalServiceBroker; - } - - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - => new RemoteCloudCachePersistentStorageService(_globalServiceBroker, workspaceServices.GetRequiredService()); - } - - private readonly IGlobalServiceBroker _globalServiceBroker; - - public RemoteCloudCachePersistentStorageService( - IGlobalServiceBroker globalServiceBroker, - IPersistentStorageConfiguration configuration) - : base(configuration) - { - _globalServiceBroker = globalServiceBroker; - } - - protected override async ValueTask CreateCacheServiceAsync(string solutionFolder, CancellationToken cancellationToken) - { - var serviceBroker = _globalServiceBroker.Instance; - -#pragma warning disable ISB001 // Dispose of proxies - // cache service will be disposed inside RemoteCloudCacheService.Dispose - var cacheService = await serviceBroker.GetProxyAsync( - VisualStudioServices.VS2019_10.CacheService, - // replace with CacheService.RelativePathBaseActivationArgKey once available. - new ServiceActivationOptions { ActivationArguments = ImmutableDictionary.Empty.Add("RelativePathBase", solutionFolder) }, - cancellationToken).ConfigureAwait(false); -#pragma warning restore ISB001 // Dispose of proxies - - Contract.ThrowIfNull(cacheService); - return cacheService; - } - } -} diff --git a/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj b/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj index 2e6ce22a7645f..2d85cd9ac2631 100644 --- a/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj +++ b/src/Workspaces/Remote/ServiceHub/Microsoft.CodeAnalysis.Remote.ServiceHub.csproj @@ -34,9 +34,6 @@ - - - diff --git a/src/Workspaces/Remote/ServiceHub/Services/SemanticClassification/RemoteSemanticClassificationService.Caching.cs b/src/Workspaces/Remote/ServiceHub/Services/SemanticClassification/RemoteSemanticClassificationService.Caching.cs index 7b983c6130e42..1abec95dd1e99 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/SemanticClassification/RemoteSemanticClassificationService.Caching.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/SemanticClassification/RemoteSemanticClassificationService.Caching.cs @@ -307,7 +307,7 @@ private static ImmutableArray Read(ObjectReader reader) using var _1 = ArrayBuilder.GetInstance(classificationTypesCount, out var classificationTypes); for (var i = 0; i < classificationTypesCount; i++) - classificationTypes.Add(reader.ReadString()); + classificationTypes.Add(reader.ReadRequiredString()); var classifiedSpanCount = reader.ReadInt32(); using var _2 = ArrayBuilder.GetInstance(classifiedSpanCount, out var classifiedSpans); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs index e01546b72e860..bceffb0f2ca48 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SemanticModelExtensions.cs @@ -465,6 +465,12 @@ public static IMethodSymbol GetRequiredDeclaredSymbol(this SemanticModel semanti ?? throw new InvalidOperationException(); } + public static IMethodSymbol GetRequiredDeclaredSymbol(this SemanticModel semanticModel, LocalFunctionStatementSyntax syntax, CancellationToken cancellationToken) + { + return semanticModel.GetDeclaredSymbol(syntax, cancellationToken) + ?? throw new InvalidOperationException(); + } + public static IParameterSymbol GetRequiredDeclaredSymbol(this SemanticModel semanticModel, ParameterSyntax syntax, CancellationToken cancellationToken) { return semanticModel.GetDeclaredSymbol(syntax, cancellationToken) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpFormattingOptions2.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpFormattingOptions2.cs index 58538fdacc359..a006d36d6cf43 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpFormattingOptions2.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpFormattingOptions2.cs @@ -24,34 +24,34 @@ internal static partial class CSharpFormattingOptions2 // Maps to store mapping between special option kinds and the corresponding editor config string representations. #region Editor Config maps private static readonly BidirectionalMap s_spacingWithinParenthesisOptionsEditorConfigMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("expressions", SpacePlacementWithinParentheses.Expressions), KeyValuePairUtil.Create("type_casts", SpacePlacementWithinParentheses.TypeCasts), KeyValuePairUtil.Create("control_flow_statements", SpacePlacementWithinParentheses.ControlFlowStatements), - }); + ]); private static readonly BidirectionalMap s_binaryOperatorSpacingOptionsEditorConfigMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("ignore", BinaryOperatorSpacingOptions.Ignore), KeyValuePairUtil.Create("none", BinaryOperatorSpacingOptions.Remove), KeyValuePairUtil.Create("before_and_after", BinaryOperatorSpacingOptions.Single), - }); + ]); private static readonly BidirectionalMap s_labelPositionOptionsEditorConfigMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("flush_left", LabelPositionOptions.LeftMost), KeyValuePairUtil.Create("no_change", LabelPositionOptions.NoIndent), KeyValuePairUtil.Create("one_less_than_current", LabelPositionOptions.OneLess), - }); + ]); private static readonly BidirectionalMap s_legacyNewLineOptionsEditorConfigMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("object_collection_array_initalizers", NewLineBeforeOpenBracePlacement.ObjectCollectionArrayInitializers), - }); + ]); private static readonly BidirectionalMap s_newLineOptionsEditorConfigMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("all", NewLineBeforeOpenBracePlacement.All), KeyValuePairUtil.Create("accessors", NewLineBeforeOpenBracePlacement.Accessors), KeyValuePairUtil.Create("types", NewLineBeforeOpenBracePlacement.Types), @@ -62,7 +62,7 @@ internal static partial class CSharpFormattingOptions2 KeyValuePairUtil.Create("anonymous_types", NewLineBeforeOpenBracePlacement.AnonymousTypes), KeyValuePairUtil.Create("object_collection_array_initializers", NewLineBeforeOpenBracePlacement.ObjectCollectionArrayInitializers), KeyValuePairUtil.Create("lambdas", NewLineBeforeOpenBracePlacement.LambdaExpressionBody), - }); + ]); #endregion internal static ImmutableArray AllOptions { get; } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs index e54df94a661f3..774aec8a2a2f0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Indentation/CSharpSmartTokenFormatter.cs @@ -64,7 +64,7 @@ public IList FormatRange( var formatter = CSharpSyntaxFormatting.Instance; var result = formatter.GetFormattingResult( - _root, new[] { TextSpan.FromBounds(startToken.SpanStart, endToken.Span.End) }, _options.FormattingOptions, smartTokenformattingRules, cancellationToken); + _root, [TextSpan.FromBounds(startToken.SpanStart, endToken.Span.End)], _options.FormattingOptions, smartTokenformattingRules, cancellationToken); return result.GetTextChanges(cancellationToken); } @@ -118,7 +118,7 @@ public IList FormatToken(SyntaxToken token, CancellationToken cancel var formatter = CSharpSyntaxFormatting.Instance; var result = formatter.GetFormattingResult( - _root, new[] { TextSpan.FromBounds(adjustedStartPosition, adjustedEndPosition) }, _options.FormattingOptions, smartTokenformattingRules, cancellationToken); + _root, [TextSpan.FromBounds(adjustedStartPosition, adjustedEndPosition)], _options.FormattingOptions, smartTokenformattingRules, cancellationToken); return result.GetTextChanges(cancellationToken); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs index e65e3a09a6d81..c7f04caee0265 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/Simplifiers/CastSimplifier.cs @@ -263,7 +263,18 @@ private static bool IsDelegateCreationCastSafeToRemove( return false; // having to be converting to the same delegate type. - return Equals(originalDelegateCreationOperation.Type, rewrittenDelegateCreationOperation.Type); + if (!Equals(originalDelegateCreationOperation.Type, rewrittenDelegateCreationOperation.Type)) + return false; + + // If there are two conversions applied on the same node, ensure both are legal. + if (originalDelegateCreationOperation.Parent is IConversionOperation conversionOperation && + conversionOperation.Syntax == castNode && + !IsConversionCastSafeToRemove(castNode, castedExpressionNode, originalSemanticModel, conversionOperation, cancellationToken)) + { + return false; + } + + return true; } private static bool IsConversionCastSafeToRemove( diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs index 5a163a9ed36a5..4ee7b2f829bf8 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs @@ -155,11 +155,11 @@ public static PerLanguageOption2> CreatePerLanguageEditorCon new(default, NotificationOption2.None); private static readonly BidirectionalMap s_unusedExpressionAssignmentPreferenceMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("discard_variable", UnusedValuePreference.DiscardVariable), KeyValuePairUtil.Create("unused_local_variable", UnusedValuePreference.UnusedLocalVariable), - }); + ]); internal static EditorConfigValueSerializer> GetUnusedValuePreferenceSerializer(CodeStyleOption2 defaultValue) => new(parseValue: str => ParseUnusedExpressionAssignmentPreference(str, defaultValue), diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs index 127a618fbd0cb..5e25a272c4cb7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs @@ -168,11 +168,11 @@ private static PerLanguageOption2> CreateQualifyAccessOpt IdeCodeStyleOptions.CommonDefaults.PreferSimplifiedInterpolation); private static readonly BidirectionalMap s_unusedParametersPreferenceMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("non_public", UnusedParametersPreference.NonPublicMethods), KeyValuePairUtil.Create("all", UnusedParametersPreference.AllMethods), - }); + ]); internal static readonly PerLanguageOption2> UnusedParameters = CreatePerLanguageOption( CodeStyleOptionGroups.Parameter, @@ -196,13 +196,13 @@ private static PerLanguageOption2> CreateQualifyAccessOpt })); private static readonly BidirectionalMap s_accessibilityModifiersRequiredMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("never", CodeStyle.AccessibilityModifiersRequired.Never), KeyValuePairUtil.Create("always", CodeStyle.AccessibilityModifiersRequired.Always), KeyValuePairUtil.Create("for_non_interface_members", CodeStyle.AccessibilityModifiersRequired.ForNonInterfaceMembers), KeyValuePairUtil.Create("omit_if_default", CodeStyle.AccessibilityModifiersRequired.OmitIfDefault), - }); + ]); internal static readonly PerLanguageOption2> AccessibilityModifiersRequired = CreatePerLanguageOption( CodeStyleOptionGroups.Modifier, "dotnet_style_require_accessibility_modifiers", @@ -242,11 +242,11 @@ private static PerLanguageOption2> CreateQualifyAccessOpt EditorConfigValueSerializer.String(emptyStringRepresentation: "none")); private static readonly BidirectionalMap s_parenthesesPreferenceMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("always_for_clarity", ParenthesesPreference.AlwaysForClarity), KeyValuePairUtil.Create("never_if_unnecessary", ParenthesesPreference.NeverIfUnnecessary), - }); + ]); private static PerLanguageOption2> CreateParenthesesOption(CodeStyleOption2 defaultValue, string name) => CreatePerLanguageOption( @@ -292,11 +292,11 @@ private static PerLanguageOption2> Creat "dotnet_style_parentheses_in_other_operators"); private static readonly BidirectionalMap s_forEachExplicitCastInSourcePreferencePreferenceMap = - new(new[] - { + new( + [ KeyValuePairUtil.Create("always", ForEachExplicitCastInSourcePreference.Always), KeyValuePairUtil.Create("when_strongly_typed", ForEachExplicitCastInSourcePreference.WhenStronglyTyped), - }); + ]); internal static readonly Option2> ForEachExplicitCastInSource = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Collections/NormalizedTextSpanCollection.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Collections/NormalizedTextSpanCollection.cs index 37435186193a5..64213fdfcfb84 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Collections/NormalizedTextSpanCollection.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Collections/NormalizedTextSpanCollection.cs @@ -535,7 +535,7 @@ public override string ToString() value.Append(s.ToString()); } - value.Append("}"); + value.Append('}'); return value.ToString(); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems index 429318aeb9e64..076af55d7cdbf 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems @@ -268,7 +268,10 @@ + + + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EditorConfig/Parsing/EditorConfigParser.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EditorConfig/Parsing/EditorConfigParser.cs index 5499baa5786c7..1441873563786 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EditorConfig/Parsing/EditorConfigParser.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/EditorConfig/Parsing/EditorConfigParser.cs @@ -18,7 +18,7 @@ internal static class EditorConfigParser private static readonly Regex s_propertyMatcher = new(@"^\s*([\w\.\-_]+)\s*[=:]\s*(.*?)\s*([#;].*)?$", RegexOptions.Compiled); private static ImmutableHashSet ReservedKeys { get; } - = ImmutableHashSet.CreateRange(AnalyzerConfigOptions.KeyComparer, new[] { + = ImmutableHashSet.CreateRange(AnalyzerConfigOptions.KeyComparer, [ "root", "indent_style", "indent_size", @@ -27,10 +27,10 @@ internal static class EditorConfigParser "charset", "trim_trailing_whitespace", "insert_final_newline", - }); + ]); private static ImmutableHashSet ReservedValues { get; } - = ImmutableHashSet.CreateRange(CaseInsensitiveComparison.Comparer, new[] { "unset" }); + = ImmutableHashSet.CreateRange(CaseInsensitiveComparison.Comparer, ["unset"]); public static TEditorConfigFile Parse(string text, string? pathToFile, TAccumulator accumulator) where TAccumulator : IEditorConfigOptionAccumulator diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ImmutableArrayExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ImmutableArrayExtensions.cs index 1c3a6acaa310f..9ec69831e8f86 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ImmutableArrayExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ImmutableArrayExtensions.cs @@ -13,11 +13,7 @@ internal static class ImmutableArrayExtensions { public static ImmutableArray ToImmutableArray(this HashSet set) { - using var _ = ArrayBuilder.GetInstance(set.Count, out var result); - foreach (var value in set) - result.Add(value); - - return result.ToImmutableAndClear(); + return [.. set]; } public static bool Contains(this ImmutableArray items, T item, IEqualityComparer? equalityComparer) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ListExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ListExtensions.cs index a65ce1aa3de69..cd11541c7b060 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ListExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ListExtensions.cs @@ -107,14 +107,5 @@ public static int IndexOf(this IList list, Func predi return -1; } - - public static void AddRangeWhere(this List list, List collection, Func predicate) - { - foreach (var element in collection) - { - if (predicate(element)) - list.Add(element); - } - } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ObjectWriterExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ObjectWriterExtensions.cs index d72be1d6dad3c..66abc90e1bc81 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ObjectWriterExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ObjectWriterExtensions.cs @@ -22,12 +22,15 @@ public static void WriteArray(this ObjectWriter writer, ImmutableArray val internal static class ObjectReaderExtensions { public static ImmutableArray ReadArray(this ObjectReader reader, Func read) + => ReadArray(reader, static (reader, read) => read(reader), read); + + public static ImmutableArray ReadArray(this ObjectReader reader, Func read, TArg arg) { var length = reader.ReadInt32(); using var _ = ArrayBuilder.GetInstance(length, out var builder); for (var i = 0; i < length; i++) - builder.Add(read(reader)); + builder.Add(read(reader, arg)); return builder.ToImmutableAndClear(); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs index ae42f2b0744a1..7f5a67b06f23c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs @@ -119,7 +119,7 @@ public void Initialize( } public void AddIndentBlockOperations( - List operations, + SegmentedList operations, CancellationToken cancellationToken) { Contract.ThrowIfNull(operations); @@ -272,39 +272,21 @@ public void AddInitialSuppressOperation(SuppressOperation operation) } public void AddSuppressOperations( - List operations, + SegmentedList operations, CancellationToken cancellationToken) { - var valuePairs = new SegmentedArray<(SuppressOperation operation, bool shouldSuppress, bool onSameLine)>(operations.Count); - // TODO: think about a way to figure out whether it is already suppressed and skip the expensive check below. - for (var i = 0; i < operations.Count; i++) + foreach (var operation in operations) { cancellationToken.ThrowIfCancellationRequested(); - var operation = operations[i]; - // if an operation contains elastic trivia itself and the operation is not marked to ignore the elastic trivia // ignore the operation if (operation.ContainsElasticTrivia(_tokenStream) && !operation.Option.IsOn(SuppressOption.IgnoreElasticWrapping)) - { - // don't bother to calculate line alignment between tokens - valuePairs[i] = (operation, shouldSuppress: false, onSameLine: false); continue; - } var onSameLine = _tokenStream.TwoTokensOriginallyOnSameLine(operation.StartToken, operation.EndToken); - valuePairs[i] = (operation, shouldSuppress: true, onSameLine); - } - - foreach (var (operation, shouldSuppress, onSameLine) in valuePairs) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (shouldSuppress) - { - AddSuppressOperation(operation, onSameLine); - } + AddSuppressOperation(operation, onSameLine); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/AbstractFormatEngine.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/AbstractFormatEngine.cs index 056326d26eaa5..804f2b41a4dfb 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/AbstractFormatEngine.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/AbstractFormatEngine.cs @@ -91,7 +91,7 @@ public AbstractFormattingResult Format(CancellationToken cancellationToken) using (Logger.LogBlock(FunctionId.Formatting_Format, FormatSummary, cancellationToken)) { // setup environment - var nodeOperations = CreateNodeOperations(cancellationToken); + using var nodeOperations = CreateNodeOperations(cancellationToken); var tokenStream = new TokenStream(this.TreeData, Options, this.SpanToFormat, CreateTriviaFactory()); using var tokenOperations = s_tokenPairListPool.GetPooledObject(); @@ -162,13 +162,17 @@ protected virtual NodeOperations CreateNodeOperations(CancellationToken cancella return nodeOperations; } - private static void AddOperations(List operations, List scratch, SyntaxNode node, Action, SyntaxNode> addOperations) + private static void AddOperations(SegmentedList operations, List scratch, SyntaxNode node, Action, SyntaxNode> addOperations) { Debug.Assert(scratch.Count == 0); addOperations(scratch, node); + foreach (var operation in scratch) + { + if (operation is not null) + operations.Add(operation); + } - operations.AddRangeWhere(scratch, static item => item is not null); scratch.Clear(); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/NodeOperations.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/NodeOperations.cs index d76367193f62d..d564304e93b4b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/NodeOperations.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Engine/NodeOperations.cs @@ -2,21 +2,47 @@ // 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.Collections.Generic; +using System; +using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Formatting.Rules; +using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.Formatting { /// /// this collector gathers formatting operations that are based on a node /// - internal class NodeOperations + internal sealed class NodeOperations : IDisposable { + private static readonly ObjectPool> s_indentBlockOperationPool = new(() => new()); + private static readonly ObjectPool> s_suppressOperationPool = new(() => new()); + private static readonly ObjectPool> s_alignTokensOperationPool = new(() => new()); + private static readonly ObjectPool> s_anchorIndentationOperationPool = new(() => new()); + public static NodeOperations Empty = new(); - public List IndentBlockOperation { get; } = new(); - public List SuppressOperation { get; } = new(); - public List AlignmentOperation { get; } = new(); - public List AnchorIndentationOperations { get; } = new(); + public SegmentedList IndentBlockOperation { get; } = s_indentBlockOperationPool.Allocate(); + public SegmentedList SuppressOperation { get; } = s_suppressOperationPool.Allocate(); + public SegmentedList AlignmentOperation { get; } = s_alignTokensOperationPool.Allocate(); + public SegmentedList AnchorIndentationOperations { get; } = s_anchorIndentationOperationPool.Allocate(); + + public void Dispose() + { + if (this == Empty) + return; + + // Intentionally don't call ClearAndFree as these pooled lists can easily exceed the threshold + IndentBlockOperation.Clear(); + s_indentBlockOperationPool.Free(IndentBlockOperation); + + SuppressOperation.Clear(); + s_suppressOperationPool.Free(SuppressOperation); + + AlignmentOperation.Clear(); + s_alignTokensOperationPool.Free(AlignmentOperation); + + AnchorIndentationOperations.Clear(); + s_anchorIndentationOperationPool.Free(AnchorIndentationOperations); + } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyle.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyle.cs index 31b0e9b513876..88a6a5b909a51 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyle.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyle.cs @@ -387,7 +387,7 @@ private string FinishFixingName(string name) } name = name[Prefix.Length..^Suffix.Length]; - IEnumerable words = new[] { name }; + IEnumerable words = [name]; if (!string.IsNullOrEmpty(WordSeparator)) { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/SharedPools.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/SharedPools.cs index b33b25ffb84da..fc19f15bf643a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/SharedPools.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/SharedPools.cs @@ -54,16 +54,11 @@ public static ObjectPool> StringIgnoreCaseDictionary() /// other I/O requests /// public static readonly ObjectPool ByteArray = new(() => new byte[ByteBufferSize], ByteBufferCount); - public static readonly ObjectPool CharArray = new(() => new char[CharBufferSize], CharBufferCount); // byte pooled memory : 4K * 512 = 2MB public const int ByteBufferSize = 4 * 1024; private const int ByteBufferCount = 512; - // char pooled memory : 8K * 256 = 2MB - public const int CharBufferSize = 4 * 1024; - private const int CharBufferCount = 256; - private static class DefaultBigPool where T : class, new() { public static readonly ObjectPool Instance = new(() => new T(), 100); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.ReaderReferenceMap.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.ReaderReferenceMap.cs new file mode 100644 index 0000000000000..7a1db7482c255 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.ReaderReferenceMap.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. + +using System; +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Roslyn.Utilities; + +internal sealed partial class ObjectReader +{ + /// + /// A reference-id to object map, that can share base data efficiently. + /// + private readonly struct ReaderReferenceMap : IDisposable + { + private readonly SegmentedList _values; + + private static readonly ObjectPool> s_objectListPool + = new(() => new SegmentedList(20)); + + private ReaderReferenceMap(SegmentedList values) + => _values = values; + + public static ReaderReferenceMap Create() + => new(s_objectListPool.Allocate()); + + public void Dispose() + { + _values.Clear(); + s_objectListPool.Free(_values); + } + + public void AddValue(string value) + => _values.Add(value); + + public string GetValue(int referenceId) + => _values[referenceId]; + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.cs index aaf80406a685a..2eabf6a5a4797 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectReader.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; using System.Diagnostics; using System.IO; @@ -11,19 +9,9 @@ using System.Text; using System.Threading; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Collections; -using Microsoft.CodeAnalysis.PooledObjects; namespace Roslyn.Utilities; -#if COMPILERCORE -using Resources = CodeAnalysisResources; -#elif CODE_STYLE -using Resources = CodeStyleResources; -#else -using Resources = WorkspacesResources; -#endif - using TypeCode = ObjectWriter.TypeCode; /// @@ -37,7 +25,7 @@ internal sealed partial class ObjectReader : IDisposable /// this version, just change VersionByte2. /// internal const byte VersionByte1 = 0b10101010; - internal const byte VersionByte2 = 0b00001100; + internal const byte VersionByte2 = 0b00001101; private readonly BinaryReader _reader; private readonly CancellationToken _cancellationToken; @@ -45,7 +33,7 @@ internal sealed partial class ObjectReader : IDisposable /// /// Map of reference id's to deserialized strings. /// - private readonly ReaderReferenceMap _stringReferenceMap; + private readonly ReaderReferenceMap _stringReferenceMap; /// /// Creates a new instance of a . @@ -63,7 +51,7 @@ private ObjectReader( Debug.Assert(BitConverter.IsLittleEndian); _reader = new BinaryReader(stream, Encoding.UTF8, leaveOpen); - _stringReferenceMap = ReaderReferenceMap.Create(); + _stringReferenceMap = ReaderReferenceMap.Create(); _cancellationToken = cancellationToken; } @@ -73,8 +61,8 @@ private ObjectReader( /// If the does not start with a valid header, then will /// be returned. /// - public static ObjectReader TryGetReader( - Stream stream, + public static ObjectReader? TryGetReader( + Stream? stream, bool leaveOpen = false, CancellationToken cancellationToken = default) { @@ -161,7 +149,9 @@ public void Dispose() public uint ReadUInt32() => _reader.ReadUInt32(); public ulong ReadUInt64() => _reader.ReadUInt64(); public ushort ReadUInt16() => _reader.ReadUInt16(); - public string ReadString() => ReadStringValue(); + public string? ReadString() => ReadStringValue(); + + public string ReadRequiredString() => ReadString() ?? throw ExceptionUtilities.Unreachable(); public Guid ReadGuid() { @@ -174,21 +164,21 @@ public Guid ReadGuid() return accessor.Guid; } - public object ReadValue() + public object? ReadScalarValue() { - var code = (TypeCode)_reader.ReadByte(); + var code = (TypeCode)ReadByte(); switch (code) { case TypeCode.Null: return null; case TypeCode.Boolean_True: return true; case TypeCode.Boolean_False: return false; - case TypeCode.Int8: return _reader.ReadSByte(); - case TypeCode.UInt8: return _reader.ReadByte(); - case TypeCode.Int16: return _reader.ReadInt16(); - case TypeCode.UInt16: return _reader.ReadUInt16(); - case TypeCode.Int32: return _reader.ReadInt32(); - case TypeCode.Int32_1Byte: return (int)_reader.ReadByte(); - case TypeCode.Int32_2Bytes: return (int)_reader.ReadUInt16(); + case TypeCode.Int8: return ReadSByte(); + case TypeCode.UInt8: return ReadByte(); + case TypeCode.Int16: return ReadInt16(); + case TypeCode.UInt16: return ReadUInt16(); + case TypeCode.Int32: return ReadInt32(); + case TypeCode.Int32_1Byte: return (int)ReadByte(); + case TypeCode.Int32_2Bytes: return (int)ReadUInt16(); case TypeCode.Int32_0: case TypeCode.Int32_1: case TypeCode.Int32_2: @@ -201,9 +191,9 @@ public object ReadValue() case TypeCode.Int32_9: case TypeCode.Int32_10: return (int)code - (int)TypeCode.Int32_0; - case TypeCode.UInt32: return _reader.ReadUInt32(); - case TypeCode.UInt32_1Byte: return (uint)_reader.ReadByte(); - case TypeCode.UInt32_2Bytes: return (uint)_reader.ReadUInt16(); + case TypeCode.UInt32: return ReadUInt32(); + case TypeCode.UInt32_1Byte: return (uint)ReadByte(); + case TypeCode.UInt32_2Bytes: return (uint)ReadUInt16(); case TypeCode.UInt32_0: case TypeCode.UInt32_1: case TypeCode.UInt32_2: @@ -216,14 +206,14 @@ public object ReadValue() case TypeCode.UInt32_9: case TypeCode.UInt32_10: return (uint)((int)code - (int)TypeCode.UInt32_0); - case TypeCode.Int64: return _reader.ReadInt64(); - case TypeCode.UInt64: return _reader.ReadUInt64(); - case TypeCode.Float4: return _reader.ReadSingle(); - case TypeCode.Float8: return _reader.ReadDouble(); - case TypeCode.Decimal: return _reader.ReadDecimal(); + case TypeCode.Int64: return ReadInt64(); + case TypeCode.UInt64: return ReadUInt64(); + case TypeCode.Float4: return ReadSingle(); + case TypeCode.Float8: return ReadDouble(); + case TypeCode.Decimal: return ReadDecimal(); case TypeCode.Char: // read as ushort because BinaryWriter fails on chars that are unicode surrogates - return (char)_reader.ReadUInt16(); + return (char)ReadUInt16(); case TypeCode.StringUtf8: case TypeCode.StringUtf16: case TypeCode.StringRef_4Bytes: @@ -231,19 +221,26 @@ public object ReadValue() case TypeCode.StringRef_2Bytes: return ReadStringValue(code); case TypeCode.DateTime: - return DateTime.FromBinary(_reader.ReadInt64()); - case TypeCode.Array: - case TypeCode.Array_0: - case TypeCode.Array_1: - case TypeCode.Array_2: - case TypeCode.Array_3: - return ReadArray(code); + return DateTime.FromBinary(ReadInt64()); + + default: + throw ExceptionUtilities.UnexpectedValue(code); + } + } + + public Encoding? ReadEncoding() + { + var code = (TypeCode)ReadByte(); + switch (code) + { + case TypeCode.Null: + return null; case TypeCode.EncodingName: - return Encoding.GetEncoding(ReadString()); + return Encoding.GetEncoding(ReadRequiredString()); case >= TypeCode.FirstWellKnownTextEncoding and <= TypeCode.LastWellKnownTextEncoding: - return ObjectWriter.ToEncodingKind(code).GetEncoding(); + return ToEncodingKind(code).GetEncoding(); case TypeCode.EncodingCodePage: return Encoding.GetEncoding(ReadInt32()); @@ -251,63 +248,47 @@ public object ReadValue() default: throw ExceptionUtilities.UnexpectedValue(code); } + + static TextEncodingKind ToEncodingKind(TypeCode code) + { + Debug.Assert(code is >= TypeCode.FirstWellKnownTextEncoding and <= TypeCode.LastWellKnownTextEncoding); + return Microsoft.CodeAnalysis.EncodingExtensions.FirstTextEncodingKind + (byte)(code - TypeCode.FirstWellKnownTextEncoding); + } } - public (char[] array, int length) ReadCharArray(Func getArray) + public byte[] ReadByteArray() { - var kind = (TypeCode)_reader.ReadByte(); - - (var length, _) = ReadArrayLengthAndElementKind(kind); - var array = getArray(length); - - var charsRead = _reader.Read(array, 0, length); - - return (array, charsRead); + var (result, _) = ReadRawArray(static (reader, array, length) => reader.Read(array, 0, length)); + return result; } - /// - /// A reference-id to object map, that can share base data efficiently. - /// - private readonly struct ReaderReferenceMap : IDisposable - where T : class + public char[] ReadCharArray() { - private readonly SegmentedList _values; - - private static readonly ObjectPool> s_objectListPool - = new(() => new SegmentedList(20)); - - private ReaderReferenceMap(SegmentedList values) - => _values = values; + var (result, _) = ReadCharArray(getArray: null); + return result; + } - public static ReaderReferenceMap Create() - => new(s_objectListPool.Allocate()); + public (char[] array, int length) ReadCharArray(Func? getArray) + => ReadRawArray(static (reader, array, length) => reader.Read(array, 0, length), getArray); - public void Dispose() - { - _values.Clear(); - s_objectListPool.Free(_values); - } - - public int GetNextObjectId() - { - var id = _values.Count; - _values.Add(null); - return id; - } + public (T[] array, int length) ReadRawArray( + Func read, + Func? getArray = null) + { + // Defer to caller provided getArray if provided. Otherwise, we'll just allocate the array ourselves. + getArray ??= static length => length == 0 ? [] : new T[length]; - public void AddValue(T value) - => _values.Add(value); + var length = ReadArrayLength(); + var array = getArray(length); - public void AddValue(int index, T value) - => _values[index] = value; + var charsRead = read(_reader, array, length); - public T GetValue(int referenceId) - => _values[referenceId]; + return (array, charsRead); } internal uint ReadCompressedUInt() { - var info = _reader.ReadByte(); + var info = ReadByte(); var marker = (byte)(info & ObjectWriter.ByteMarkerMask); var byte0 = (byte)(info & ~ObjectWriter.ByteMarkerMask); @@ -318,15 +299,15 @@ internal uint ReadCompressedUInt() if (marker == ObjectWriter.Byte2Marker) { - var byte1 = _reader.ReadByte(); + var byte1 = ReadByte(); return (((uint)byte0) << 8) | byte1; } if (marker == ObjectWriter.Byte4Marker) { - var byte1 = _reader.ReadByte(); - var byte2 = _reader.ReadByte(); - var byte3 = _reader.ReadByte(); + var byte1 = ReadByte(); + var byte2 = ReadByte(); + var byte3 = ReadByte(); return (((uint)byte0) << 24) | (((uint)byte1) << 16) | (((uint)byte2) << 8) | byte3; } @@ -334,9 +315,9 @@ internal uint ReadCompressedUInt() throw ExceptionUtilities.UnexpectedValue(marker); } - private string ReadStringValue() + private string? ReadStringValue() { - var kind = (TypeCode)_reader.ReadByte(); + var kind = (TypeCode)ReadByte(); return kind == TypeCode.Null ? null : ReadStringValue(kind); } @@ -344,9 +325,9 @@ private string ReadStringValue(TypeCode kind) { return kind switch { - TypeCode.StringRef_1Byte => _stringReferenceMap.GetValue(_reader.ReadByte()), - TypeCode.StringRef_2Bytes => _stringReferenceMap.GetValue(_reader.ReadUInt16()), - TypeCode.StringRef_4Bytes => _stringReferenceMap.GetValue(_reader.ReadInt32()), + TypeCode.StringRef_1Byte => _stringReferenceMap.GetValue(ReadByte()), + TypeCode.StringRef_2Bytes => _stringReferenceMap.GetValue(ReadUInt16()), + TypeCode.StringRef_4Bytes => _stringReferenceMap.GetValue(ReadInt32()), TypeCode.StringUtf16 or TypeCode.StringUtf8 => ReadStringLiteral(kind), _ => throw ExceptionUtilities.UnexpectedValue(kind), }; @@ -374,24 +355,8 @@ private unsafe string ReadStringLiteral(TypeCode kind) return value; } - private Array ReadArray(TypeCode kind) - { - var (length, elementKind) = ReadArrayLengthAndElementKind(kind); - - var elementType = ObjectWriter.s_reverseTypeMap[(int)elementKind]; - if (elementType != null) - { - return this.ReadPrimitiveTypeArrayElements(elementType, elementKind, length); - } - else - { - throw ExceptionUtilities.UnexpectedValue(elementKind); - } - } - - private (int length, TypeCode elementKind) ReadArrayLengthAndElementKind(TypeCode kind) - { - var length = kind switch + private int ReadArrayLength() + => (TypeCode)ReadByte() switch { TypeCode.Array_0 => 0, TypeCode.Array_1 => 1, @@ -399,214 +364,4 @@ private Array ReadArray(TypeCode kind) TypeCode.Array_3 => 3, _ => (int)this.ReadCompressedUInt(), }; - - // SUBTLE: If it was a primitive array, only the EncodingKind byte of the element type was written, instead of encoding as a type. - var elementKind = (TypeCode)_reader.ReadByte(); - - return (length, elementKind); - } - - private Array ReadPrimitiveTypeArrayElements(Type type, TypeCode kind, int length) - { - Debug.Assert(ObjectWriter.s_reverseTypeMap[(int)kind] == type); - - // optimizations for supported array type by binary reader - if (type == typeof(byte)) - return _reader.ReadBytes(length); - if (type == typeof(char)) - return _reader.ReadChars(length); - - // optimizations for string where object reader/writer has its own mechanism to - // reduce duplicated strings - if (type == typeof(string)) - return ReadStringArrayElements(CreateArray(length)); - if (type == typeof(bool)) - return ReadBooleanArrayElements(CreateArray(length)); - - // otherwise, read elements directly from underlying binary writer - return kind switch - { - TypeCode.Int8 => ReadInt8ArrayElements(CreateArray(length)), - TypeCode.Int16 => ReadInt16ArrayElements(CreateArray(length)), - TypeCode.Int32 => ReadInt32ArrayElements(CreateArray(length)), - TypeCode.Int64 => ReadInt64ArrayElements(CreateArray(length)), - TypeCode.UInt16 => ReadUInt16ArrayElements(CreateArray(length)), - TypeCode.UInt32 => ReadUInt32ArrayElements(CreateArray(length)), - TypeCode.UInt64 => ReadUInt64ArrayElements(CreateArray(length)), - TypeCode.Float4 => ReadFloat4ArrayElements(CreateArray(length)), - TypeCode.Float8 => ReadFloat8ArrayElements(CreateArray(length)), - TypeCode.Decimal => ReadDecimalArrayElements(CreateArray(length)), - _ => throw ExceptionUtilities.UnexpectedValue(kind), - }; - } - - private bool[] ReadBooleanArrayElements(bool[] array) - { - // Confirm the type to be read below is ulong - Debug.Assert(BitVector.BitsPerWord == 64); - - var wordLength = BitVector.WordsRequired(array.Length); - - var count = 0; - for (var i = 0; i < wordLength; i++) - { - var word = _reader.ReadUInt64(); - - for (var p = 0; p < BitVector.BitsPerWord; p++) - { - if (count >= array.Length) - { - return array; - } - - array[count++] = BitVector.IsTrue(word, p); - } - } - - return array; - } - - private static T[] CreateArray(int length) - { - if (length == 0) - { - // quick check - return []; - } - else - { - return new T[length]; - } - } - - private string[] ReadStringArrayElements(string[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = this.ReadStringValue(); - } - - return array; - } - - private sbyte[] ReadInt8ArrayElements(sbyte[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadSByte(); - } - - return array; - } - - private short[] ReadInt16ArrayElements(short[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadInt16(); - } - - return array; - } - - private int[] ReadInt32ArrayElements(int[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadInt32(); - } - - return array; - } - - private long[] ReadInt64ArrayElements(long[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadInt64(); - } - - return array; - } - - private ushort[] ReadUInt16ArrayElements(ushort[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadUInt16(); - } - - return array; - } - - private uint[] ReadUInt32ArrayElements(uint[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadUInt32(); - } - - return array; - } - - private ulong[] ReadUInt64ArrayElements(ulong[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadUInt64(); - } - - return array; - } - - private decimal[] ReadDecimalArrayElements(decimal[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadDecimal(); - } - - return array; - } - - private float[] ReadFloat4ArrayElements(float[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadSingle(); - } - - return array; - } - - private double[] ReadFloat8ArrayElements(double[] array) - { - for (var i = 0; i < array.Length; i++) - { - array[i] = _reader.ReadDouble(); - } - - return array; - } - - public Type ReadType() - { - _reader.ReadByte(); - return Type.GetType(ReadString()); - } - - private static Exception DeserializationReadIncorrectNumberOfValuesException(string typeName) - { - throw new InvalidOperationException(String.Format(Resources.Deserialization_reader_for_0_read_incorrect_number_of_values, typeName)); - } - - private static Exception NoSerializationTypeException(string typeName) - { - return new InvalidOperationException(string.Format(Resources.The_type_0_is_not_understood_by_the_serialization_binder, typeName)); - } - - private static Exception NoSerializationReaderException(string typeName) - { - return new InvalidOperationException(string.Format(Resources.Cannot_serialize_type_0, typeName)); - } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.TypeCode.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.TypeCode.cs new file mode 100644 index 0000000000000..ab91fe4ae1b4d --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.TypeCode.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. +// See the LICENSE file in the project root for more information. + +using System.Text; +using Microsoft.CodeAnalysis; +using EncodingExtensions = Microsoft.CodeAnalysis.EncodingExtensions; + +namespace Roslyn.Utilities; + +internal sealed partial class ObjectWriter +{ + internal enum TypeCode : byte + { + /// + /// The null value + /// + Null, + + /// + /// A string encoded as UTF-8 (using BinaryWriter.Write(string)) + /// + StringUtf8, + + /// + /// A string encoded as UTF16 (as array of UInt16 values) + /// + StringUtf16, + + /// + /// A reference to a string with the id encoded as 1 byte. + /// + StringRef_1Byte, + + /// + /// A reference to a string with the id encoded as 2 bytes. + /// + StringRef_2Bytes, + + /// + /// A reference to a string with the id encoded as 4 bytes. + /// + StringRef_4Bytes, + + /// + /// The boolean value true. + /// + Boolean_True, + + /// + /// The boolean value char. + /// + Boolean_False, + + /// + /// A character value encoded as 2 bytes. + /// + Char, + + /// + /// An Int8 value encoded as 1 byte. + /// + Int8, + + /// + /// An Int16 value encoded as 2 bytes. + /// + Int16, + + /// + /// An Int32 value encoded as 4 bytes. + /// + Int32, + + /// + /// An Int32 value encoded as 1 byte. + /// + Int32_1Byte, + + /// + /// An Int32 value encoded as 2 bytes. + /// + Int32_2Bytes, + + /// + /// The Int32 value 0 + /// + Int32_0, + + /// + /// The Int32 value 1 + /// + Int32_1, + + /// + /// The Int32 value 2 + /// + Int32_2, + + /// + /// The Int32 value 3 + /// + Int32_3, + + /// + /// The Int32 value 4 + /// + Int32_4, + + /// + /// The Int32 value 5 + /// + Int32_5, + + /// + /// The Int32 value 6 + /// + Int32_6, + + /// + /// The Int32 value 7 + /// + Int32_7, + + /// + /// The Int32 value 8 + /// + Int32_8, + + /// + /// The Int32 value 9 + /// + Int32_9, + + /// + /// The Int32 value 10 + /// + Int32_10, + + /// + /// An Int64 value encoded as 8 bytes + /// + Int64, + + /// + /// A UInt8 value encoded as 1 byte. + /// + UInt8, + + /// + /// A UIn16 value encoded as 2 bytes. + /// + UInt16, + + /// + /// A UInt32 value encoded as 4 bytes. + /// + UInt32, + + /// + /// A UInt32 value encoded as 1 byte. + /// + UInt32_1Byte, + + /// + /// A UInt32 value encoded as 2 bytes. + /// + UInt32_2Bytes, + + /// + /// The UInt32 value 0 + /// + UInt32_0, + + /// + /// The UInt32 value 1 + /// + UInt32_1, + + /// + /// The UInt32 value 2 + /// + UInt32_2, + + /// + /// The UInt32 value 3 + /// + UInt32_3, + + /// + /// The UInt32 value 4 + /// + UInt32_4, + + /// + /// The UInt32 value 5 + /// + UInt32_5, + + /// + /// The UInt32 value 6 + /// + UInt32_6, + + /// + /// The UInt32 value 7 + /// + UInt32_7, + + /// + /// The UInt32 value 8 + /// + UInt32_8, + + /// + /// The UInt32 value 9 + /// + UInt32_9, + + /// + /// The UInt32 value 10 + /// + UInt32_10, + + /// + /// A UInt64 value encoded as 8 bytes. + /// + UInt64, + + /// + /// A float value encoded as 4 bytes. + /// + Float4, + + /// + /// A double value encoded as 8 bytes. + /// + Float8, + + /// + /// A decimal value encoded as 12 bytes. + /// + Decimal, + + /// + /// A DateTime value + /// + DateTime, + + /// + /// An array with length encoded as compressed uint + /// + Array, + + /// + /// An array with zero elements + /// + Array_0, + + /// + /// An array with one element + /// + Array_1, + + /// + /// An array with 2 elements + /// + Array_2, + + /// + /// An array with 3 elements + /// + Array_3, + + /// + /// Encoding serialized as . + /// + EncodingName, + + /// + /// Encoding serialized as . + /// + FirstWellKnownTextEncoding, + LastWellKnownTextEncoding = FirstWellKnownTextEncoding + EncodingExtensions.LastTextEncodingKind - EncodingExtensions.FirstTextEncodingKind, + + /// + /// Encoding serialized as . + /// + EncodingCodePage, + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.WriterReferenceMap.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.WriterReferenceMap.cs new file mode 100644 index 0000000000000..d0a4b2a77fbb0 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.WriterReferenceMap.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. + +using Microsoft.CodeAnalysis.Collections; +using Microsoft.CodeAnalysis.PooledObjects; + +namespace Roslyn.Utilities; + +internal sealed partial class ObjectWriter +{ + /// + /// An object reference to reference-id map, that can share base data efficiently. + /// + private struct WriterReferenceMap + { + // PERF: Use segmented collection to avoid Large Object Heap allocations during serialization. + // https://github.com/dotnet/roslyn/issues/43401 + private readonly SegmentedDictionary _valueToIdMap; + private int _nextId; + + private static readonly ObjectPool> s_valueDictionaryPool = new(() => new(128)); + + public WriterReferenceMap() + { + _valueToIdMap = s_valueDictionaryPool.Allocate(); + _nextId = 0; + } + + public readonly void Dispose() + { + // If the map grew too big, don't return it to the pool. + // When testing with the Roslyn solution, this dropped only 2.5% of requests. + if (_valueToIdMap.Count > 1024) + { + s_valueDictionaryPool.ForgetTrackedObject(_valueToIdMap); + } + else + { + _valueToIdMap.Clear(); + s_valueDictionaryPool.Free(_valueToIdMap); + } + } + + public bool TryGetReferenceId(string value, out int referenceId) + => _valueToIdMap.TryGetValue(value, out referenceId); + + public void Add(string value) + { + var id = _nextId++; + _valueToIdMap.Add(value, id); + } + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.cs index 86574d9468595..14e95e5bdafd1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Serialization/ObjectWriter.cs @@ -3,25 +3,19 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; -using Microsoft.CodeAnalysis.Collections; -using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.PooledObjects; using EncodingExtensions = Microsoft.CodeAnalysis.EncodingExtensions; namespace Roslyn.Utilities { - using System.Collections.Immutable; - using System.Threading.Tasks; -#if COMPILERCORE - using Resources = CodeAnalysisResources; -#elif CODE_STYLE +#if CODE_STYLE using Resources = CodeStyleResources; #else using Resources = WorkspacesResources; @@ -32,6 +26,32 @@ namespace Roslyn.Utilities /// internal sealed partial class ObjectWriter : IDisposable { + private static class BufferPool + { + // Large arrays that will not go into the LOH (even with System.Char). + public static ObjectPool Shared = new(() => new T[32768], 512); + } + + /// + /// byte marker mask for encoding compressed uint + /// + public const byte ByteMarkerMask = 3 << 6; + + /// + /// byte marker bits for uint encoded in 1 byte. + /// + public const byte Byte1Marker = 0; + + /// + /// byte marker bits for uint encoded in 2 bytes. + /// + public const byte Byte2Marker = 1 << 6; + + /// + /// byte marker bits for uint encoded in 4 bytes. + /// + public const byte Byte4Marker = 2 << 6; + private readonly BinaryWriter _writer; private readonly CancellationToken _cancellationToken; @@ -80,8 +100,8 @@ public ObjectWriter( private void WriteVersion() { - _writer.Write(ObjectReader.VersionByte1); - _writer.Write(ObjectReader.VersionByte2); + WriteByte(ObjectReader.VersionByte1); + WriteByte(ObjectReader.VersionByte2); } public void Dispose() @@ -128,13 +148,18 @@ public void WriteGuid(Guid guid) WriteInt64(accessor.High64); } - public void WriteValue(object? value) + /// + /// Only supports values of primitive scaler types. This really should only be used to emit VB preprocessor + /// symbol values (which are scaler, but untyped as 'object'). Callers which know their value's type should + /// call into that directly. + /// + public void WriteScalarValue(object? value) { Debug.Assert(value == null || !value.GetType().GetTypeInfo().IsEnum, "Enum should not be written with WriteValue. Write them as ints instead."); if (value == null) { - _writer.Write((byte)TypeCode.Null); + WriteByte((byte)TypeCode.Null); return; } @@ -145,61 +170,61 @@ public void WriteValue(object? value) // Perf: Note that JIT optimizes each expression value.GetType() == typeof(T) to a single register comparison. // Also the checks are sorted by commonality of the checked types. - // The primitive types are - // Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, - // Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single. + // The list supported can be found in CConst.TryCreate. + + // The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, + // UIntPtr, Char, Double, and Single. if (typeInfo.IsPrimitive) { - // Note: int, double, bool, char, have been chosen to go first as they're they - // common values of literals in code, and so would be the likely hits if we do - // have a primitive type we're serializing out. + // Note: int, double, bool, char, have been chosen to go first as they're they common values of literals + // in code, and so would be the likely hits if we do have a primitive type we're serializing out. if (value.GetType() == typeof(int)) { WriteEncodedInt32((int)value); } else if (value.GetType() == typeof(double)) { - _writer.Write((byte)TypeCode.Float8); - _writer.Write((double)value); + WriteByte((byte)TypeCode.Float8); + WriteDouble((double)value); } else if (value.GetType() == typeof(bool)) { - _writer.Write((byte)((bool)value ? TypeCode.Boolean_True : TypeCode.Boolean_False)); + WriteByte((byte)((bool)value ? TypeCode.Boolean_True : TypeCode.Boolean_False)); } else if (value.GetType() == typeof(char)) { - _writer.Write((byte)TypeCode.Char); - _writer.Write((ushort)(char)value); // written as ushort because BinaryWriter fails on chars that are unicode surrogates + WriteByte((byte)TypeCode.Char); + WriteChar((char)value); } else if (value.GetType() == typeof(byte)) { - _writer.Write((byte)TypeCode.UInt8); - _writer.Write((byte)value); + WriteByte((byte)TypeCode.UInt8); + WriteByte((byte)value); } else if (value.GetType() == typeof(short)) { - _writer.Write((byte)TypeCode.Int16); - _writer.Write((short)value); + WriteByte((byte)TypeCode.Int16); + WriteInt16((short)value); } else if (value.GetType() == typeof(long)) { - _writer.Write((byte)TypeCode.Int64); - _writer.Write((long)value); + WriteByte((byte)TypeCode.Int64); + WriteInt64((long)value); } else if (value.GetType() == typeof(sbyte)) { - _writer.Write((byte)TypeCode.Int8); - _writer.Write((sbyte)value); + WriteByte((byte)TypeCode.Int8); + WriteSByte((sbyte)value); } else if (value.GetType() == typeof(float)) { - _writer.Write((byte)TypeCode.Float4); - _writer.Write((float)value); + WriteByte((byte)TypeCode.Float4); + WriteSingle((float)value); } else if (value.GetType() == typeof(ushort)) { - _writer.Write((byte)TypeCode.UInt16); - _writer.Write((ushort)value); + WriteByte((byte)TypeCode.UInt16); + WriteUInt16((ushort)value); } else if (value.GetType() == typeof(uint)) { @@ -207,8 +232,8 @@ public void WriteValue(object? value) } else if (value.GetType() == typeof(ulong)) { - _writer.Write((byte)TypeCode.UInt64); - _writer.Write((ulong)value); + WriteByte((byte)TypeCode.UInt64); + WriteUInt64((ulong)value); } else { @@ -217,108 +242,131 @@ public void WriteValue(object? value) } else if (value.GetType() == typeof(decimal)) { - _writer.Write((byte)TypeCode.Decimal); - _writer.Write((decimal)value); + WriteByte((byte)TypeCode.Decimal); + WriteDecimal((decimal)value); } else if (value.GetType() == typeof(DateTime)) { - _writer.Write((byte)TypeCode.DateTime); + WriteByte((byte)TypeCode.DateTime); _writer.Write(((DateTime)value).ToBinary()); } else if (value.GetType() == typeof(string)) { WriteStringValue((string)value); } - else if (type.IsArray) - { - var instance = (Array)value; - - if (instance.Rank > 1) - { - throw new InvalidOperationException(Resources.Arrays_with_more_than_one_dimension_cannot_be_serialized); - } - - WriteArray(instance); - } - else if (value is Encoding encoding) - { - WriteEncoding(encoding); - } else { throw new InvalidOperationException($"Unsupported object type: {value.GetType()}"); } } + public void WriteByteArray(byte[] array) + { + WriteArrayLength(array.Length); + _writer.Write(array); + } + + public void WriteCharArray(char[] array) + { + WriteArrayLength(array.Length); + _writer.Write(array); + } + /// - /// Write an array of bytes. The array data is provided as a - /// ReadOnlySpan<>, and deserialized to a byte array. + /// Write an array of bytes. The array data is provided as a ReadOnlySpan<>, and deserialized to a byte array. /// /// The array data. - public void WriteValue(ReadOnlySpan span) + public void WriteSpan(ReadOnlySpan span) + { + WriteArrayLength(span.Length); + +#if NETCOREAPP + _writer.Write(span); +#else + // BinaryWriter in .NET Framework does not support ReadOnlySpan, so we use a temporary buffer to write + // arrays of data. + WriteSpanPieces(span, static (writer, buffer, length) => writer.Write(buffer, 0, length)); +#endif + } + + /// + /// Write an array of chars. The array data is provided as a ReadOnlySpan<>, and deserialized to a char array. + /// + /// The array data. + public void WriteSpan(ReadOnlySpan span) + { + WriteArrayLength(span.Length); + +#if NETCOREAPP + _writer.Write(span); +#else + // BinaryWriter in .NET Framework does not support ReadOnlySpan, so we use a temporary buffer to write + // arrays of data. + WriteSpanPieces(span, static (writer, buffer, length) => writer.Write(buffer, 0, length)); +#endif + } + + private void WriteArrayLength(int length) { - var length = span.Length; switch (length) { case 0: - _writer.Write((byte)TypeCode.Array_0); + WriteByte((byte)TypeCode.Array_0); break; case 1: - _writer.Write((byte)TypeCode.Array_1); + WriteByte((byte)TypeCode.Array_1); break; case 2: - _writer.Write((byte)TypeCode.Array_2); + WriteByte((byte)TypeCode.Array_2); break; case 3: - _writer.Write((byte)TypeCode.Array_3); + WriteByte((byte)TypeCode.Array_3); break; default: - _writer.Write((byte)TypeCode.Array); + WriteByte((byte)TypeCode.Array); WriteCompressedUInt((uint)length); break; } + } - var elementType = typeof(byte); - Debug.Assert(s_typeMap[elementType] == TypeCode.UInt8); - - WritePrimitiveType(elementType, TypeCode.UInt8); + private void WriteSpanPieces( + ReadOnlySpan span, + Action write) + { + var spanLength = span.Length; + using var pooledObj = BufferPool.Shared.GetPooledObject(); + var buffer = pooledObj.Object; -#if NETCOREAPP - _writer.Write(span); -#else - // BinaryWriter in .NET Framework does not support ReadOnlySpan, so we use a temporary buffer to write - // arrays of data. The buffer is chosen to be no larger than 8K, which avoids allocations in the large - // object heap. - var buffer = new byte[Math.Min(length, 8192)]; - for (var offset = 0; offset < length; offset += buffer.Length) + for (var offset = 0; offset < spanLength; offset += buffer.Length) { - var segmentLength = Math.Min(buffer.Length, length - offset); + var segmentLength = Math.Min(buffer.Length, spanLength - offset); span.Slice(offset, segmentLength).CopyTo(buffer.AsSpan()); - _writer.Write(buffer, 0, segmentLength); + write(_writer, buffer, segmentLength); } -#endif } private void WriteEncodedInt32(int v) { if (v >= 0 && v <= 10) { - _writer.Write((byte)((int)TypeCode.Int32_0 + v)); + WriteByte((byte)((int)TypeCode.Int32_0 + v)); } else if (v >= 0 && v < byte.MaxValue) { - _writer.Write((byte)TypeCode.Int32_1Byte); - _writer.Write((byte)v); + WriteByte((byte)TypeCode.Int32_1Byte); + WriteByte((byte)v); } else if (v >= 0 && v < ushort.MaxValue) { - _writer.Write((byte)TypeCode.Int32_2Bytes); - _writer.Write((ushort)v); + WriteByte((byte)TypeCode.Int32_2Bytes); + WriteUInt16((ushort)v); } else { - _writer.Write((byte)TypeCode.Int32); - _writer.Write(v); + WriteByte((byte)TypeCode.Int32); + WriteInt32(v); } } @@ -326,70 +374,22 @@ private void WriteEncodedUInt32(uint v) { if (v >= 0 && v <= 10) { - _writer.Write((byte)((int)TypeCode.UInt32_0 + v)); + WriteByte((byte)((int)TypeCode.UInt32_0 + v)); } else if (v >= 0 && v < byte.MaxValue) { - _writer.Write((byte)TypeCode.UInt32_1Byte); - _writer.Write((byte)v); + WriteByte((byte)TypeCode.UInt32_1Byte); + WriteByte((byte)v); } else if (v >= 0 && v < ushort.MaxValue) { - _writer.Write((byte)TypeCode.UInt32_2Bytes); - _writer.Write((ushort)v); + WriteByte((byte)TypeCode.UInt32_2Bytes); + WriteUInt16((ushort)v); } else { - _writer.Write((byte)TypeCode.UInt32); - _writer.Write(v); - } - } - - /// - /// An object reference to reference-id map, that can share base data efficiently. - /// - private struct WriterReferenceMap - { - // PERF: Use segmented collection to avoid Large Object Heap allocations during serialization. - // https://github.com/dotnet/roslyn/issues/43401 - private readonly SegmentedDictionary _valueToIdMap; - private int _nextId; - - private static readonly ObjectPool> s_valueDictionaryPool = - new(() => new SegmentedDictionary(128)); - - public WriterReferenceMap() - { - _valueToIdMap = s_valueDictionaryPool.Allocate(); - _nextId = 0; - } - - public void Dispose() - { - // If the map grew too big, don't return it to the pool. - // When testing with the Roslyn solution, this dropped only 2.5% of requests. - if (_valueToIdMap.Count > 1024) - { - s_valueDictionaryPool.ForgetTrackedObject(_valueToIdMap); - } - else - { - _valueToIdMap.Clear(); - s_valueDictionaryPool.Free(_valueToIdMap); - } - } - - public bool TryGetReferenceId(object value, out int referenceId) - => _valueToIdMap.TryGetValue(value, out referenceId); - - public void Add(object value, bool isReusable) - { - var id = _nextId++; - - if (isReusable) - { - _valueToIdMap.Add(value, id); - } + WriteByte((byte)TypeCode.UInt32); + WriteUInt32(v); } } @@ -397,7 +397,7 @@ internal void WriteCompressedUInt(uint value) { if (value <= (byte.MaxValue >> 2)) { - _writer.Write((byte)value); + WriteByte((byte)value); } else if (value <= (ushort.MaxValue >> 2)) { @@ -405,8 +405,8 @@ internal void WriteCompressedUInt(uint value) var byte1 = (byte)(value & 0xFFu); // high-bytes to low-bytes - _writer.Write(byte0); - _writer.Write(byte1); + WriteByte(byte0); + WriteByte(byte1); } else if (value <= (uint.MaxValue >> 2)) { @@ -416,10 +416,10 @@ internal void WriteCompressedUInt(uint value) var byte3 = (byte)(value & 0xFFu); // high-bytes to low-bytes - _writer.Write(byte0); - _writer.Write(byte1); - _writer.Write(byte2); - _writer.Write(byte3); + WriteByte(byte0); + WriteByte(byte1); + WriteByte(byte2); + WriteByte(byte3); } else { @@ -431,7 +431,7 @@ private unsafe void WriteStringValue(string? value) { if (value == null) { - _writer.Write((byte)TypeCode.Null); + WriteByte((byte)TypeCode.Null); } else { @@ -440,35 +440,35 @@ private unsafe void WriteStringValue(string? value) Debug.Assert(id >= 0); if (id <= byte.MaxValue) { - _writer.Write((byte)TypeCode.StringRef_1Byte); - _writer.Write((byte)id); + WriteByte((byte)TypeCode.StringRef_1Byte); + WriteByte((byte)id); } else if (id <= ushort.MaxValue) { - _writer.Write((byte)TypeCode.StringRef_2Bytes); - _writer.Write((ushort)id); + WriteByte((byte)TypeCode.StringRef_2Bytes); + WriteUInt16((ushort)id); } else { - _writer.Write((byte)TypeCode.StringRef_4Bytes); - _writer.Write(id); + WriteByte((byte)TypeCode.StringRef_4Bytes); + WriteInt32(id); } } else { - _stringReferenceMap.Add(value, isReusable: true); + _stringReferenceMap.Add(value); if (value.IsValidUnicodeString()) { // Usual case - the string can be encoded as UTF-8: // We can use the UTF-8 encoding of the binary writer. - _writer.Write((byte)TypeCode.StringUtf8); + WriteByte((byte)TypeCode.StringUtf8); _writer.Write(value); } else { - _writer.Write((byte)TypeCode.StringUtf16); + WriteByte((byte)TypeCode.StringUtf16); // This is rare, just allocate UTF16 bytes for simplicity. var bytes = new byte[(uint)value.Length * sizeof(char)]; @@ -484,232 +484,6 @@ private unsafe void WriteStringValue(string? value) } } - private void WriteArray(Array array) - { - var length = array.GetLength(0); - - switch (length) - { - case 0: - _writer.Write((byte)TypeCode.Array_0); - break; - case 1: - _writer.Write((byte)TypeCode.Array_1); - break; - case 2: - _writer.Write((byte)TypeCode.Array_2); - break; - case 3: - _writer.Write((byte)TypeCode.Array_3); - break; - default: - _writer.Write((byte)TypeCode.Array); - this.WriteCompressedUInt((uint)length); - break; - } - - var elementType = array.GetType().GetElementType()!; - - if (s_typeMap.TryGetValue(elementType, out var elementKind)) - { - this.WritePrimitiveType(elementType, elementKind); - this.WritePrimitiveTypeArrayElements(elementType, elementKind, array); - } - else - { - throw new InvalidOperationException($"Unsupported array element type: {elementType}"); - } - } - - private void WriteArrayValues(Array array) - { - for (var i = 0; i < array.Length; i++) - { - this.WriteValue(array.GetValue(i)); - } - } - - private void WritePrimitiveTypeArrayElements(Type type, TypeCode kind, Array instance) - { - Debug.Assert(s_typeMap[type] == kind); - - // optimization for type underlying binary writer knows about - if (type == typeof(byte)) - { - _writer.Write((byte[])instance); - } - else if (type == typeof(char)) - { - _writer.Write((char[])instance); - } - else if (type == typeof(string)) - { - // optimization for string which object writer has - // its own optimization to reduce repeated string - WriteStringArrayElements((string[])instance); - } - else if (type == typeof(bool)) - { - // optimization for bool array - WriteBooleanArrayElements((bool[])instance); - } - else - { - // otherwise, write elements directly to underlying binary writer - switch (kind) - { - case TypeCode.Int8: - WriteInt8ArrayElements((sbyte[])instance); - return; - case TypeCode.Int16: - WriteInt16ArrayElements((short[])instance); - return; - case TypeCode.Int32: - WriteInt32ArrayElements((int[])instance); - return; - case TypeCode.Int64: - WriteInt64ArrayElements((long[])instance); - return; - case TypeCode.UInt16: - WriteUInt16ArrayElements((ushort[])instance); - return; - case TypeCode.UInt32: - WriteUInt32ArrayElements((uint[])instance); - return; - case TypeCode.UInt64: - WriteUInt64ArrayElements((ulong[])instance); - return; - case TypeCode.Float4: - WriteFloat4ArrayElements((float[])instance); - return; - case TypeCode.Float8: - WriteFloat8ArrayElements((double[])instance); - return; - case TypeCode.Decimal: - WriteDecimalArrayElements((decimal[])instance); - return; - default: - throw ExceptionUtilities.UnexpectedValue(kind); - } - } - } - - private void WriteBooleanArrayElements(bool[] array) - { - // convert bool array to bit array - var bits = BitVector.Create(array.Length); - for (var i = 0; i < array.Length; i++) - { - bits[i] = array[i]; - } - - // send over bit array - foreach (var word in bits.Words()) - { - _writer.Write(word); - } - } - - private void WriteStringArrayElements(string[] array) - { - for (var i = 0; i < array.Length; i++) - { - WriteStringValue(array[i]); - } - } - - private void WriteInt8ArrayElements(sbyte[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteInt16ArrayElements(short[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteInt32ArrayElements(int[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteInt64ArrayElements(long[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteUInt16ArrayElements(ushort[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteUInt32ArrayElements(uint[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteUInt64ArrayElements(ulong[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteDecimalArrayElements(decimal[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteFloat4ArrayElements(float[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WriteFloat8ArrayElements(double[] array) - { - for (var i = 0; i < array.Length; i++) - { - _writer.Write(array[i]); - } - } - - private void WritePrimitiveType(Type type, TypeCode kind) - { - Debug.Assert(s_typeMap[type] == kind); - _writer.Write((byte)kind); - } - - public void WriteType(Type type) - { - _writer.Write((byte)TypeCode.Type); - this.WriteString(type.AssemblyQualifiedName); - } - public void WriteEncoding(Encoding? encoding) { if (encoding == null) @@ -730,374 +504,14 @@ public void WriteEncoding(Encoding? encoding) WriteByte((byte)TypeCode.EncodingName); WriteString(encoding.WebName); } - } - // we have s_typeMap and s_reversedTypeMap since there is no bidirectional map in compiler - // Note: s_typeMap is effectively immutable. However, for maximum perf we use mutable types because - // they are used in hotspots. - internal static readonly Dictionary s_typeMap; + return; - /// - /// Indexed by . - /// - internal static readonly ImmutableArray s_reverseTypeMap; - - static ObjectWriter() - { - s_typeMap = new Dictionary + static TypeCode ToTypeCode(TextEncodingKind kind) { - { typeof(bool), TypeCode.BooleanType }, - { typeof(char), TypeCode.Char }, - { typeof(string), TypeCode.StringType }, - { typeof(sbyte), TypeCode.Int8 }, - { typeof(short), TypeCode.Int16 }, - { typeof(int), TypeCode.Int32 }, - { typeof(long), TypeCode.Int64 }, - { typeof(byte), TypeCode.UInt8 }, - { typeof(ushort), TypeCode.UInt16 }, - { typeof(uint), TypeCode.UInt32 }, - { typeof(ulong), TypeCode.UInt64 }, - { typeof(float), TypeCode.Float4 }, - { typeof(double), TypeCode.Float8 }, - { typeof(decimal), TypeCode.Decimal }, - }; - - var temp = new Type[(int)TypeCode.Last]; - - foreach (var kvp in s_typeMap) - { - temp[(int)kvp.Value] = kvp.Key; + Debug.Assert(kind is >= EncodingExtensions.FirstTextEncodingKind and <= EncodingExtensions.LastTextEncodingKind); + return TypeCode.FirstWellKnownTextEncoding + (byte)(kind - EncodingExtensions.FirstTextEncodingKind); } - - s_reverseTypeMap = ImmutableArray.Create(temp); - } - - /// - /// byte marker mask for encoding compressed uint - /// - internal const byte ByteMarkerMask = 3 << 6; - - /// - /// byte marker bits for uint encoded in 1 byte. - /// - internal const byte Byte1Marker = 0; - - /// - /// byte marker bits for uint encoded in 2 bytes. - /// - internal const byte Byte2Marker = 1 << 6; - - /// - /// byte marker bits for uint encoded in 4 bytes. - /// - internal const byte Byte4Marker = 2 << 6; - - internal enum TypeCode : byte - { - /// - /// The null value - /// - Null, - - /// - /// A type - /// - Type, - - /// - /// A string encoded as UTF-8 (using BinaryWriter.Write(string)) - /// - StringUtf8, - - /// - /// A string encoded as UTF16 (as array of UInt16 values) - /// - StringUtf16, - - /// - /// A reference to a string with the id encoded as 1 byte. - /// - StringRef_1Byte, - - /// - /// A reference to a string with the id encoded as 2 bytes. - /// - StringRef_2Bytes, - - /// - /// A reference to a string with the id encoded as 4 bytes. - /// - StringRef_4Bytes, - - /// - /// The boolean value true. - /// - Boolean_True, - - /// - /// The boolean value char. - /// - Boolean_False, - - /// - /// A character value encoded as 2 bytes. - /// - Char, - - /// - /// An Int8 value encoded as 1 byte. - /// - Int8, - - /// - /// An Int16 value encoded as 2 bytes. - /// - Int16, - - /// - /// An Int32 value encoded as 4 bytes. - /// - Int32, - - /// - /// An Int32 value encoded as 1 byte. - /// - Int32_1Byte, - - /// - /// An Int32 value encoded as 2 bytes. - /// - Int32_2Bytes, - - /// - /// The Int32 value 0 - /// - Int32_0, - - /// - /// The Int32 value 1 - /// - Int32_1, - - /// - /// The Int32 value 2 - /// - Int32_2, - - /// - /// The Int32 value 3 - /// - Int32_3, - - /// - /// The Int32 value 4 - /// - Int32_4, - - /// - /// The Int32 value 5 - /// - Int32_5, - - /// - /// The Int32 value 6 - /// - Int32_6, - - /// - /// The Int32 value 7 - /// - Int32_7, - - /// - /// The Int32 value 8 - /// - Int32_8, - - /// - /// The Int32 value 9 - /// - Int32_9, - - /// - /// The Int32 value 10 - /// - Int32_10, - - /// - /// An Int64 value encoded as 8 bytes - /// - Int64, - - /// - /// A UInt8 value encoded as 1 byte. - /// - UInt8, - - /// - /// A UIn16 value encoded as 2 bytes. - /// - UInt16, - - /// - /// A UInt32 value encoded as 4 bytes. - /// - UInt32, - - /// - /// A UInt32 value encoded as 1 byte. - /// - UInt32_1Byte, - - /// - /// A UInt32 value encoded as 2 bytes. - /// - UInt32_2Bytes, - - /// - /// The UInt32 value 0 - /// - UInt32_0, - - /// - /// The UInt32 value 1 - /// - UInt32_1, - - /// - /// The UInt32 value 2 - /// - UInt32_2, - - /// - /// The UInt32 value 3 - /// - UInt32_3, - - /// - /// The UInt32 value 4 - /// - UInt32_4, - - /// - /// The UInt32 value 5 - /// - UInt32_5, - - /// - /// The UInt32 value 6 - /// - UInt32_6, - - /// - /// The UInt32 value 7 - /// - UInt32_7, - - /// - /// The UInt32 value 8 - /// - UInt32_8, - - /// - /// The UInt32 value 9 - /// - UInt32_9, - - /// - /// The UInt32 value 10 - /// - UInt32_10, - - /// - /// A UInt64 value encoded as 8 bytes. - /// - UInt64, - - /// - /// A float value encoded as 4 bytes. - /// - Float4, - - /// - /// A double value encoded as 8 bytes. - /// - Float8, - - /// - /// A decimal value encoded as 12 bytes. - /// - Decimal, - - /// - /// A DateTime value - /// - DateTime, - - /// - /// An array with length encoded as compressed uint - /// - Array, - - /// - /// An array with zero elements - /// - Array_0, - - /// - /// An array with one element - /// - Array_1, - - /// - /// An array with 2 elements - /// - Array_2, - - /// - /// An array with 3 elements - /// - Array_3, - - /// - /// The boolean type - /// - BooleanType, - - /// - /// The string type - /// - StringType, - - /// - /// Encoding serialized as . - /// - EncodingName, - - /// - /// Encoding serialized as . - /// - FirstWellKnownTextEncoding, - LastWellKnownTextEncoding = FirstWellKnownTextEncoding + EncodingExtensions.LastTextEncodingKind - EncodingExtensions.FirstTextEncodingKind, - - /// - /// Encoding serialized as . - /// - EncodingCodePage, - - Last, - } - - internal static TypeCode ToTypeCode(TextEncodingKind kind) - { - Debug.Assert(kind is >= EncodingExtensions.FirstTextEncodingKind and <= EncodingExtensions.LastTextEncodingKind); - return TypeCode.FirstWellKnownTextEncoding + (byte)(kind - EncodingExtensions.FirstTextEncodingKind); - } - - internal static TextEncodingKind ToEncodingKind(TypeCode code) - { - Debug.Assert(code is >= TypeCode.FirstWellKnownTextEncoding and <= TypeCode.LastWellKnownTextEncoding); - return EncodingExtensions.FirstTextEncodingKind + (byte)(code - TypeCode.FirstWellKnownTextEncoding); } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.Serialization.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.Serialization.cs index 818daea5d941b..44f3418cf29b0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.Serialization.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.Serialization.cs @@ -3,7 +3,7 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Roslyn.Utilities; @@ -11,38 +11,19 @@ internal readonly partial struct BKTree { internal void WriteTo(ObjectWriter writer) { - writer.WriteInt32(_concatenatedLowerCaseWords.Length); - foreach (var c in _concatenatedLowerCaseWords) - writer.WriteChar(c); - - writer.WriteInt32(_nodes.Length); - foreach (var node in _nodes) - node.WriteTo(writer); - - writer.WriteInt32(_edges.Length); - foreach (var edge in _edges) - edge.WriteTo(writer); + writer.WriteCharArray(_concatenatedLowerCaseWords); + writer.WriteArray(_nodes, static (w, n) => n.WriteTo(w)); + writer.WriteArray(_edges, static (w, n) => n.WriteTo(w)); } internal static BKTree? ReadFrom(ObjectReader reader) { try { - var concatenatedLowerCaseWords = new char[reader.ReadInt32()]; - for (var i = 0; i < concatenatedLowerCaseWords.Length; i++) - concatenatedLowerCaseWords[i] = reader.ReadChar(); - - var nodeCount = reader.ReadInt32(); - using var _1 = ArrayBuilder.GetInstance(nodeCount, out var nodes); - for (var i = 0; i < nodeCount; i++) - nodes.Add(Node.ReadFrom(reader)); - - var edgeCount = reader.ReadInt32(); - using var _2 = ArrayBuilder.GetInstance(edgeCount, out var edges); - for (var i = 0; i < edgeCount; i++) - edges.Add(Edge.ReadFrom(reader)); - - return new BKTree(concatenatedLowerCaseWords, nodes.ToImmutableAndClear(), edges.ToImmutableAndClear()); + return new BKTree( + reader.ReadCharArray(), + reader.ReadArray(Node.ReadFrom), + reader.ReadArray(Edge.ReadFrom)); } catch { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/CompilerUtilities/ImmutableHashMap.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/CompilerUtilities/ImmutableHashMap.cs index 734ac4b9f7adf..01de36dcd3e24 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/CompilerUtilities/ImmutableHashMap.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/CompilerUtilities/ImmutableHashMap.cs @@ -451,17 +451,17 @@ public override string ToString() foreach (var kv in this) { builder.Append(kv.Key); - builder.Append(":"); + builder.Append(':'); builder.Append(kv.Value); if (needComma) { - builder.Append(","); + builder.Append(','); } needComma = true; } - builder.Append("]"); + builder.Append(']'); return builder.ToString(); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Utilities/CastAnalyzer.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Utilities/CastAnalyzer.vb index 31939f2043a0b..7515a334c7eb2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Utilities/CastAnalyzer.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Utilities/CastAnalyzer.vb @@ -10,7 +10,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Utilities Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions - Friend Class CastAnalyzer + Friend NotInheritable Class CastAnalyzer Private ReadOnly _castNode As ExpressionSyntax Private ReadOnly _castExpressionNode As ExpressionSyntax Private ReadOnly _semanticModel As SemanticModel @@ -18,12 +18,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Private ReadOnly _cancellationToken As CancellationToken Private Sub New( - castNode As ExpressionSyntax, - castExpressionNode As ExpressionSyntax, - semanticModel As SemanticModel, - assumeCallKeyword As Boolean, - cancellationToken As CancellationToken - ) + castNode As ExpressionSyntax, + castExpressionNode As ExpressionSyntax, + semanticModel As SemanticModel, + assumeCallKeyword As Boolean, + cancellationToken As CancellationToken) _castNode = castNode _castExpressionNode = castExpressionNode _semanticModel = semanticModel @@ -36,9 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Dim argument = TryCast(_castNode.WalkUpParentheses().Parent, ArgumentSyntax) If argument IsNot Nothing Then Dim parameter = argument.DetermineParameter(_semanticModel, cancellationToken:=_cancellationToken) - If parameter IsNot Nothing AndAlso parameter.IsParams Then - Debug.Assert(TypeOf parameter.Type Is IArrayTypeSymbol) - + If parameter?.IsParams = True AndAlso TypeOf parameter.Type Is IArrayTypeSymbol Then Dim parameterType = DirectCast(parameter.Type, IArrayTypeSymbol) Dim conversion = _semanticModel.Compilation.ClassifyConversion(castType, parameterType) @@ -397,9 +394,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Private Shared Function CastRemovalChangesDefaultValue(castType As ITypeSymbol, outerType As ITypeSymbol) As Boolean If castType.IsNumericType() Then Return Not outerType.IsNumericType() - ElseIf castType.SpecialType = SpecialType.System_DateTime + ElseIf castType.SpecialType = SpecialType.System_DateTime Then Return Not outerType.SpecialType = SpecialType.System_DateTime - ElseIf castType.SpecialType = SpecialType.System_Boolean + ElseIf castType.SpecialType = SpecialType.System_Boolean Then Return Not (outerType.IsNumericType OrElse outerType.SpecialType = SpecialType.System_Boolean) End If diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/CompilationUnitSyntaxExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/CompilationUnitSyntaxExtensions.cs index dd3c0922a0a63..9f0d7efe46358 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/CompilationUnitSyntaxExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/CompilationUnitSyntaxExtensions.cs @@ -83,7 +83,7 @@ public static CompilationUnitSyntax AddUsingDirective( bool placeSystemNamespaceFirst, params SyntaxAnnotation[] annotations) { - return root.AddUsingDirectives(new[] { usingDirective }, contextNode, placeSystemNamespaceFirst, annotations); + return root.AddUsingDirectives([usingDirective], contextNode, placeSystemNamespaceFirst, annotations); } public static CompilationUnitSyntax AddUsingDirectives( diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs index 4ee638237da88..2ef1dead59333 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs @@ -108,7 +108,12 @@ public override TypeSyntax VisitArrayType(IArrayTypeSymbol symbol) } public override TypeSyntax VisitDynamicType(IDynamicTypeSymbol symbol) - => AddInformationTo(SyntaxFactory.IdentifierName("dynamic"), symbol); + { + var typeSyntax = SyntaxFactory.IdentifierName("dynamic"); + return symbol.NullableAnnotation is NullableAnnotation.Annotated + ? AddInformationTo(SyntaxFactory.NullableType(typeSyntax), symbol) + : AddInformationTo(typeSyntax, symbol); + } public static bool TryCreateNativeIntegerType(INamedTypeSymbol symbol, [NotNullWhen(true)] out TypeSyntax? syntax) { @@ -133,10 +138,10 @@ public override TypeSyntax VisitFunctionPointerType(IFunctionPointerTypeSymbol s { var conventionsList = symbol.Signature.CallingConvention switch { - System.Reflection.Metadata.SignatureCallingConvention.CDecl => new[] { GetConventionForString("Cdecl") }, - System.Reflection.Metadata.SignatureCallingConvention.StdCall => new[] { GetConventionForString("Stdcall") }, - System.Reflection.Metadata.SignatureCallingConvention.ThisCall => new[] { GetConventionForString("Thiscall") }, - System.Reflection.Metadata.SignatureCallingConvention.FastCall => new[] { GetConventionForString("Fastcall") }, + System.Reflection.Metadata.SignatureCallingConvention.CDecl => [GetConventionForString("Cdecl")], + System.Reflection.Metadata.SignatureCallingConvention.StdCall => [GetConventionForString("Stdcall")], + System.Reflection.Metadata.SignatureCallingConvention.ThisCall => [GetConventionForString("Thiscall")], + System.Reflection.Metadata.SignatureCallingConvention.FastCall => [GetConventionForString("Fastcall")], System.Reflection.Metadata.SignatureCallingConvention.Unmanaged => // All types that come from CallingConventionTypes start with "CallConv". We don't want the prefix for the actual // syntax, so strip it off diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs index f6a94fb47d157..0559c51564a84 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs @@ -2296,23 +2296,20 @@ private IEnumerable InferTypeInVariableComponentAssignment(Ex // Attempt to determine what x and y are based on their future usage. if (declExpr.Type.IsVar && declExpr.Designation is ParenthesizedVariableDesignationSyntax parenthesizedVariableDesignation && - parenthesizedVariableDesignation.Variables.All(v => v is SingleVariableDesignationSyntax)) + parenthesizedVariableDesignation.Variables.All(v => v is SingleVariableDesignationSyntax { Identifier.ValueText: not "" })) { - using var _1 = ArrayBuilder.GetInstance(out var tupleTypes); - using var _2 = ArrayBuilder.GetInstance(out var names); - - foreach (var variable in parenthesizedVariableDesignation.Variables.Cast()) + var elementNames = parenthesizedVariableDesignation.Variables.SelectAsArray(v => ((SingleVariableDesignationSyntax)v).Identifier.ValueText); + var elementTypes = parenthesizedVariableDesignation.Variables.SelectAsArray(v => { - var symbol = SemanticModel.GetRequiredDeclaredSymbol(variable, CancellationToken); + var designation = (SingleVariableDesignationSyntax)v; + + var symbol = SemanticModel.GetRequiredDeclaredSymbol(designation, CancellationToken); var inferredFutureUsage = InferTypeBasedOnLaterUsage(symbol, afterNode: left.Parent); - tupleTypes.Add(inferredFutureUsage.Length > 0 ? inferredFutureUsage[0].InferredType : Compilation.ObjectType); - names.Add(variable.Identifier.ValueText); - } + return inferredFutureUsage.Length > 0 ? inferredFutureUsage[0].InferredType : Compilation.ObjectType; + }); return SpecializedCollections.SingletonEnumerable(new TypeInferenceInfo( - Compilation.CreateTupleTypeSymbol( - tupleTypes.ToImmutable(), - names.ToImmutable()))); + Compilation.CreateTupleTypeSymbol(elementTypes, elementNames))); } return GetTypes(declExpr.Type); @@ -2322,14 +2319,12 @@ declExpr.Designation is ParenthesizedVariableDesignationSyntax parenthesizedVari // We have something of the form: // (int a, int b) = ... // - // This is a deconstruction, and a decent deconstructable type we can infer here - // is ValueTuple. + // This is a deconstruction, and a decent deconstructable type we can infer here is + // ValueTuple. var tupleType = GetTupleType(tupleExpression); if (tupleType != null) - { return CreateResult(tupleType); - } } return SpecializedCollections.EmptyEnumerable(); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ISolutionExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ISolutionExtensions.cs index 63763320a91fc..3c42e6876f5fe 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ISolutionExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ISolutionExtensions.cs @@ -45,7 +45,20 @@ public static Project GetRequiredProject(this Solution solution, ProjectId proje } public static Document GetRequiredDocument(this Solution solution, DocumentId documentId) - => solution.GetDocument(documentId) ?? throw CreateDocumentNotFoundException(); + { + if (documentId is null) + throw new ArgumentNullException(nameof(documentId)); + +#if !CODE_STYLE + // If we get a source-generated DocumentId, we can give a different exception to make it clear the type of failure this is; otherwise a failure of + // this in the wild is hard to guess whether this is because of a logic bug in the feature (where it tried to use a DocumentId for a document that disappeared) + // or whether it hasn't been correctly updated to handle source generated files. + if (documentId.IsSourceGenerated) + throw new ArgumentException($"{nameof(GetRequiredDocument)} was given a source-generated DocumentId, but it will never return a source generated document. The caller needs to be calling some other method."); +#endif + + return solution.GetDocument(documentId) ?? throw CreateDocumentNotFoundException(); + } #if !CODE_STYLE public static async ValueTask GetRequiredDocumentAsync(this Solution solution, DocumentId documentId, bool includeSourceGenerated = false, CancellationToken cancellationToken = default) diff --git a/src/Workspaces/TestAnalyzerReference/NonSourceFileRefactoring.cs b/src/Workspaces/TestAnalyzerReference/NonSourceFileRefactoring.cs index 1833915aaa3a2..6b085616c0440 100644 --- a/src/Workspaces/TestAnalyzerReference/NonSourceFileRefactoring.cs +++ b/src/Workspaces/TestAnalyzerReference/NonSourceFileRefactoring.cs @@ -15,8 +15,8 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings #pragma warning disable RS0034 // Exported parts should be marked with 'ImportingConstructorAttribute' [ExportCodeRefactoringProvider( LanguageNames.CSharp, - DocumentKinds = new[] { nameof(TextDocumentKind.AdditionalDocument), nameof(TextDocumentKind.AnalyzerConfigDocument) }, - DocumentExtensions = new[] { ".txt", ".editorconfig" })] + DocumentKinds = [nameof(TextDocumentKind.AdditionalDocument), nameof(TextDocumentKind.AnalyzerConfigDocument)], + DocumentExtensions = [".txt", ".editorconfig"])] [Shared] public sealed class NonSourceFileRefactoring : CodeRefactoringProvider { diff --git a/src/Workspaces/VisualBasic/Portable/Serialization/VisualBasicOptionsSerializationService.vb b/src/Workspaces/VisualBasic/Portable/Serialization/VisualBasicOptionsSerializationService.vb index e3689929d2b48..9061a014285f1 100644 --- a/src/Workspaces/VisualBasic/Portable/Serialization/VisualBasicOptionsSerializationService.vb +++ b/src/Workspaces/VisualBasic/Portable/Serialization/VisualBasicOptionsSerializationService.vb @@ -23,7 +23,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Serialization Dim vbOptions = DirectCast(options, VisualBasicCompilationOptions) - writer.WriteValue(vbOptions.GlobalImports.Select(Function(g) g.Name).ToArray()) + writer.WriteArray(vbOptions.GlobalImports.SelectAsArray(Function(g) g.Name), Sub(w, n) w.WriteString(n)) writer.WriteString(vbOptions.RootNamespace) writer.WriteInt32(vbOptions.OptionStrict) writer.WriteBoolean(vbOptions.OptionInfer) @@ -50,43 +50,38 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Serialization writer.WriteString(kv.Key) ' all value here should be primitive types - writer.WriteValue(kv.Value) + writer.WriteScalarValue(kv.Value) Next End Sub Public Overrides Function ReadCompilationOptionsFrom(reader As ObjectReader, cancellationToken As CancellationToken) As CompilationOptions - Dim outputKind As OutputKind - Dim reportSuppressedDiagnostics As Boolean - Dim moduleName As String = Nothing - Dim mainTypeName As String = Nothing - Dim scriptClassName As String = Nothing - Dim optimizationLevel As OptimizationLevel - Dim checkOverflow As Boolean - Dim cryptoKeyContainer As String = Nothing - Dim cryptoKeyFile As String = Nothing - Dim cryptoPublicKey As ImmutableArray(Of Byte) = ImmutableArray(Of Byte).Empty - Dim delaySign As Boolean? - Dim platform As Platform - Dim generalDiagnosticOption As ReportDiagnostic - Dim warningLevel As Integer - Dim specificDiagnosticOptions As IEnumerable(Of KeyValuePair(Of String, ReportDiagnostic)) = Nothing - Dim concurrentBuild As Boolean - Dim deterministic As Boolean - Dim publicSign As Boolean - Dim metadataImportOptions As MetadataImportOptions = Nothing - Dim xmlReferenceResolver As XmlReferenceResolver = Nothing - Dim sourceReferenceResolver As SourceReferenceResolver = Nothing - Dim metadataReferenceResolver As MetadataReferenceResolver = Nothing - Dim assemblyIdentityComparer As AssemblyIdentityComparer = Nothing - Dim strongNameProvider As StrongNameProvider = Nothing - - ReadCompilationOptionsFrom(reader, outputKind, reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName, - optimizationLevel, checkOverflow, cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, - platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions, concurrentBuild, deterministic, - publicSign, metadataImportOptions, xmlReferenceResolver, sourceReferenceResolver, metadataReferenceResolver, - assemblyIdentityComparer, strongNameProvider, cancellationToken) - - Dim globalImports = GlobalImport.Parse(reader.ReadArray(Of String)()) + Dim tuple = ReadCompilationOptionsPieces(reader, cancellationToken) + Dim outputKind = tuple.outputKind + Dim reportSuppressedDiagnostics = tuple.reportSuppressedDiagnostics + Dim moduleName = tuple.moduleName + Dim mainTypeName = tuple.mainTypeName + Dim scriptClassName = tuple.scriptClassName + Dim optimizationLevel = tuple.optimizationLevel + Dim checkOverflow = tuple.checkOverflow + Dim cryptoKeyContainer = tuple.cryptoKeyContainer + Dim cryptoKeyFile = tuple.cryptoKeyFile + Dim cryptoPublicKey = tuple.cryptoPublicKey + Dim delaySign = tuple.delaySign + Dim platform = tuple.platform + Dim generalDiagnosticOption = tuple.generalDiagnosticOption + Dim warningLevel = tuple.warningLevel + Dim specificDiagnosticOptions = tuple.specificDiagnosticOptions + Dim concurrentBuild = tuple.concurrentBuild + Dim deterministic = tuple.deterministic + Dim publicSign = tuple.publicSign + Dim metadataImportOptions = tuple.metadataImportOptions + Dim xmlReferenceResolver = tuple.xmlReferenceResolver + Dim sourceReferenceResolver = tuple.sourceReferenceResolver + Dim metadataReferenceResolver = tuple.metadataReferenceResolver + Dim assemblyIdentityComparer = tuple.assemblyIdentityComparer + Dim strongNameProvider = tuple.strongNameProvider + + Dim globalImports = GlobalImport.Parse(reader.ReadArray(Function(r) r.ReadString())) Dim rootNamespace = reader.ReadString() Dim optionStrict = CType(reader.ReadInt32(), OptionStrict) Dim optionInfer = reader.ReadBoolean() @@ -108,10 +103,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Serialization End Function Public Overrides Function ReadParseOptionsFrom(reader As ObjectReader, cancellationToken As CancellationToken) As ParseOptions - Dim kind As SourceCodeKind - Dim documentationMode As DocumentationMode - Dim features As IEnumerable(Of KeyValuePair(Of String, String)) = Nothing - ReadParseOptionsFrom(reader, kind, documentationMode, features, cancellationToken) + Dim tuple = ReadParseOptionsPieces(reader, cancellationToken) + Dim kind = tuple.kind + Dim documentationMode = tuple.documentationMode + Dim features = tuple.features Dim languageVersion = DirectCast(reader.ReadInt32(), LanguageVersion) @@ -119,7 +114,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Serialization Dim builder = ImmutableArray.CreateBuilder(Of KeyValuePair(Of String, Object))(count) For i = 0 To count - 1 Dim key = reader.ReadString() - Dim value = reader.ReadValue() + Dim value = reader.ReadScalarValue() builder.Add(KeyValuePairUtil.Create(key, value)) Next