diff --git a/.vscode/launch.json b/.vscode/launch.json
index ae371f1da31ef..5c446623b4d14 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,7 +12,10 @@
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/artifacts/bin/BuildValidator/Debug/netcoreapp3.1/BuildValidator.dll",
"args": [
- "--assembliesPath", "./artifacts/obj/RunTests",
+ "--assembliesPath", "./artifacts/obj/csc/Debug/netcoreapp3.1",
+ "--referencesPath", "./artifacts/bin",
+ "--referencesPath", "C:/Program Files/dotnet/packs/Microsoft.AspNetCore.App.Ref",
+ "--referencesPath", "C:/Program Files/dotnet/packs/Microsoft.NETCore.App.Ref",
"--debugPath", "./artifacts/BuildValidator",
"--sourcePath", "."
],
diff --git a/Compilers.sln b/Compilers.sln
index db88bef2fa1b9..f833a6ddd327c 100644
--- a/Compilers.sln
+++ b/Compilers.sln
@@ -182,6 +182,7 @@ Global
src\Analyzers\VisualBasic\Analyzers\VisualBasicAnalyzers.projitems*{2531a8c4-97dd-47bc-a79c-b7846051e137}*SharedItemsImports = 5
src\Workspaces\SharedUtilitiesAndExtensions\Compiler\VisualBasic\VisualBasicCompilerExtensions.projitems*{2531a8c4-97dd-47bc-a79c-b7846051e137}*SharedItemsImports = 5
src\Analyzers\Core\Analyzers\Analyzers.projitems*{275812ee-dedb-4232-9439-91c9757d2ae4}*SharedItemsImports = 5
+ src\Dependencies\Collections\Microsoft.CodeAnalysis.Collections.projitems*{275812ee-dedb-4232-9439-91c9757d2ae4}*SharedItemsImports = 5
src\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems*{275812ee-dedb-4232-9439-91c9757d2ae4}*SharedItemsImports = 5
src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\CompilerExtensions.projitems*{275812ee-dedb-4232-9439-91c9757d2ae4}*SharedItemsImports = 5
src\Compilers\Core\CommandLine\CommandLine.projitems*{4b45ca0c-03a0-400f-b454-3d4bcb16af38}*SharedItemsImports = 5
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index 6cfb4daece861..54cf4819baf2a 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -18,10 +18,7 @@ jobs:
- job: VS_Integration
pool:
name: NetCorePublic-Pool
- queue: BuildPool.Windows.VS2019.Pre.Scouting.Open
-# One this integration test fix has flowed in to master-vs-deps, we can update the queueName variable, and revert this change.
-# Tracked by https://github.com/dotnet/roslyn/issues/51312
-# queue: $(queueName)
+ queue: $(queueName)
strategy:
maxParallel: 4
matrix:
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 3f27b27861f96..4b6a45dc352d7 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -26,18 +26,26 @@ variables:
- group: DotNet-GitHub-Versions-Repo-Write
- name: _DevDivDropAccessToken
value: $(System.AccessToken)
+ # For publishing from devdiv pipeline to devdiv feed, the API key can
+ # be any non-empty string as authentication is done in the pipeline.
+ - name: _DevDivNugetFeedAccessToken
+ value: "AzureArtifacts"
# If the pipeline is running in dnceng:
- # Get access token with $dn-bot-devdiv-drop-rw-code-rw from DotNet-VSTS-Infra-Access
+ # Get access token with $dn-bot-devdiv-drop-rw-code-rw and dn-bot-dnceng-build-rw-code-rw from DotNet-VSTS-Infra-Access
# Get $dotnetfeed-storage-access-key-1 from DotNet-Blob-Feed
# Get $microsoft-symbol-server-pat and $symweb-symbol-server-pat from DotNet-Symbol-Server-Pats
# Get $AccessToken-dotnet-build-bot-public-repo from DotNet-Versions-Publish
+ # Get $dn-bot-devdiv-packaging-rw from DotNet-DevDiv-Insertion-Workflow-Variables
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- group: DotNet-Blob-Feed
- group: DotNet-Symbol-Server-Pats
- group: DotNet-Versions-Publish
- group: DotNet-VSTS-Infra-Access
+ - group: DotNet-DevDiv-Insertion-Workflow-Variables
- name: _DevDivDropAccessToken
value: $(dn-bot-devdiv-drop-rw-code-rw)
+ - name: _DevDivNugetFeedAccessToken
+ value: $(dn-bot-devdiv-packaging-rw)
stages:
- stage: build
@@ -109,7 +117,11 @@ stages:
- task: PowerShell@2
displayName: Merge master-vs-deps into source branch
inputs:
- filePath: 'scripts\merge-vs-deps.ps1'
+ filePath: 'scripts\merge-vs-deps.ps1'
+ ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}:
+ arguments: '-userName "$(Build.RequestedFor)" -userEmail $(Build.RequestedForEmail)'
+ ${{ if eq(variables['System.TeamProject'], 'internal') }}:
+ arguments: '-userName "$(Build.RequestedFor)" -userEmail $(Build.RequestedForEmail) -accessToken $(dn-bot-dnceng-build-rw-code-rw)'
condition: and(succeeded(), eq(variables['SourceBranchName'], 'master'))
- powershell: Write-Host "##vso[task.setvariable variable=VisualStudio.DropName]Products/$(System.TeamProject)/$(Build.Repository.Name)/$(SourceBranchName)/$(Build.BuildNumber)"
@@ -180,7 +192,7 @@ stages:
displayName: Publish Assets
inputs:
filePath: 'eng\publish-assets.ps1'
- arguments: '-configuration $(BuildConfiguration) -branchName "$(SourceBranchName)" -gitHubUserName $(Roslyn.GitHubUserName) -gitHubToken $(AccessToken-dotnet-build-bot-public-repo) -gitHubEmail $(Roslyn.GitHubEmail)'
+ arguments: '-configuration $(BuildConfiguration) -branchName "$(SourceBranchName)" -gitHubUserName $(Roslyn.GitHubUserName) -gitHubToken $(AccessToken-dotnet-build-bot-public-repo) -gitHubEmail $(Roslyn.GitHubEmail) -devdivApiKey $(_DevDivNugetFeedAccessToken)'
condition: and(succeeded(), eq(variables['PRNumber'], 'default'))
# Publish OptProf configuration files
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index bb28e7fecfffc..3d1e6a024468e 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -215,7 +215,8 @@ jobs:
- job: Correctness_Rebuild
pool:
- vmImage: windows-2019
+ name: NetCorePublic-Pool
+ queue: BuildPool.Windows.10.Amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
@@ -226,13 +227,7 @@ jobs:
filePath: eng/build.ps1
arguments: -configuration Debug -prepareMachine -ci -restore -binaryLog
- - task: PowerShell@2
- displayName: Build
- inputs:
- filePath: eng/build.ps1
- arguments: -configuration Debug -prepareMachine -ci -build -bootstrap -publish -binaryLog -skipDocumentation
-
- - script: .\artifacts\bin\BuildValidator\Debug\net472\BuildValidator.exe --assembliesPath .\artifacts\obj\Microsoft.CodeAnalysis --debugPath .\artifacts\BuildValidator --sourcePath .
+ - powershell: .\eng\test-rebuild.ps1 -ci -configuration Release
displayName: Run BuildValidator
- task: PublishBuildArtifacts@1
diff --git a/docs/Language Feature Status.md b/docs/Language Feature Status.md
index 5169d06e14f14..e77488bef3d5a 100644
--- a/docs/Language Feature Status.md
+++ b/docs/Language Feature Status.md
@@ -8,25 +8,29 @@ efforts behind them.
# C# Next
-| Feature | Branch | State | Developers | Reviewer | LDM Champ |
-|----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------------|-----------------------------------------|
-| [Record structs](https://github.com/dotnet/csharplang/issues/4334) | [record-structs](https://github.com/dotnet/roslyn/tree/features/record-structs) | [In Progress](https://github.com/dotnet/roslyn/issues/51199) | [jcouv](https://github.com/jcouv) | TBD | [jcouv](https://github.com/jcouv) |
-| [Global Using Directive](https://github.com/dotnet/csharplang/issues/3428) | [GlobalUsingDirective](https://github.com/dotnet/roslyn/tree/features/GlobalUsingDirective) | [In Progress](https://github.com/dotnet/roslyn/issues/51307) | [AlekseyTs](https://github.com/AlekseyTs) | TBD | [AlekseyTs](https://github.com/AlekseyTs) |
-| [nameof(parameter)](https://github.com/dotnet/csharplang/issues/373) | master | [In Progress](https://github.com/dotnet/roslyn/issues/40524) | [jcouv](https://github.com/jcouv) | TBD | [jcouv](https://github.com/jcouv) |
-| [Relax ordering of `ref` and `partial` modifiers](https://github.com/dotnet/csharplang/issues/946) | [ref-partial](https://github.com/dotnet/roslyn/tree/features/ref-partial) | In Progress | [alrz](https://github.com/alrz) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) |
-| [Parameter null-checking](https://github.com/dotnet/csharplang/issues/2145) | [param-nullchecking](https://github.com/dotnet/roslyn/tree/features/param-nullchecking) | [In Progress](https://github.com/dotnet/roslyn/issues/36024) | [fayrose](https://github.com/fayrose) | [agocke](https://github.com/agocke) | [jaredpar](https://github.com/jaredpar) |
-| [Caller expression attribute](https://github.com/dotnet/csharplang/issues/287) | [caller-expression](https://github.com/dotnet/roslyn/tree/features/caller-expression) | Prototype | [alrz](https://github.com/alrz) | [jcouv](https://github.com/jcouv) | [jcouv](https://github.com/jcouv) |
-| [Generic attributes](https://github.com/dotnet/csharplang/issues/124) | [generic-attributes](https://github.com/dotnet/roslyn/tree/features/generic-attributes) | [In Progress](https://github.com/dotnet/roslyn/issues/36285) | [AviAvni](https://github.com/AviAvni) | [agocke](https://github.com/agocke) | [mattwar](https://github.com/mattwar) |
-| [Default in deconstruction](https://github.com/dotnet/roslyn/pull/25562) | [decon-default](https://github.com/dotnet/roslyn/tree/features/decon-default) | [Implemented](https://github.com/dotnet/roslyn/issues/25559) | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) |
-| [Constant Interpolated Strings](https://github.com/dotnet/csharplang/issues/2951) | master | [Merged into 16.9p3](https://github.com/dotnet/roslyn/pull/49676) | [kevinsun-dev](https://github.com/kevinsun-dev) | [333fred](https://github.com/333fred) | [jaredar](https://github.com/jaredpar), [agocke](https://github.com/agocke) |
-| [Mix declarations and variables in deconstruction](https://github.com/dotnet/csharplang/issues/125) | master | [Merged into 16.10](https://github.com/dotnet/roslyn/issues/47746) | [YairHalberstadt ](https://github.com/YairHalberstadt ) | [jcouv](https://github.com/jcouv) | [MadsTorgersen](https://github.com/MadsTorgersen) |
+| Feature | Branch | State | Developers | Reviewer | LDM Champ |
+| ------- | ------ | ----- | ---------- | -------- | --------- |
+| [Record structs](https://github.com/dotnet/csharplang/issues/4334) | [record-structs](https://github.com/dotnet/roslyn/tree/features/record-structs) | [In Progress](https://github.com/dotnet/roslyn/issues/51199) | [jcouv](https://github.com/jcouv) | [AlekseyTs](https://github.com/AlekseyTs), [RikkiGibson](https://github.com/RikkiGibson) | [jcouv](https://github.com/jcouv) |
+| [Global Using Directive](https://github.com/dotnet/csharplang/issues/3428) | [GlobalUsingDirective](https://github.com/dotnet/roslyn/tree/features/GlobalUsingDirective) | [In Progress](https://github.com/dotnet/roslyn/issues/51307) | [AlekseyTs](https://github.com/AlekseyTs) | [333fred](https://github.com/333fred), [cston](https://github.com/cston) | [AlekseyTs](https://github.com/AlekseyTs) |
+| [File-scoped namespace](https://github.com/dotnet/csharplang/issues/137) | [FileScopedNamespaces](https://github.com/dotnet/roslyn/tree/features/FileScopedNamespaces) | In Progress | [chsienki](https://github.com/chsienki) | [cston](https://github.com/cston), [RikkiGibson](https://github.com/RikkiGibson) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) |
+| [Interpolated string improvements](https://github.com/dotnet/csharplang/issues/2302) | [interpolated-string](https://github.com/dotnet/roslyn/tree/features/interpolated-string) | [In Progress](https://github.com/dotnet/roslyn/issues/51499) | [333fred](https://github.com/333fred) | [AlekseyTs](https://github.com/AlekseyTs), [chsienki](https://github.com/chsienki) | [jaredpar](https://github.com/jaredpar) |
+| [Parameterless struct constructors](https://github.com/dotnet/csharplang/issues/99) | TBD | In Progress | [cston](https://github.com/cston) | [jcouv](https://github.com/jcouv), [333fred](https://github.com/333fred) | [jcouv](https://github.com/jouv) |
+| [nameof(parameter)](https://github.com/dotnet/csharplang/issues/373) | master | [In Progress](https://github.com/dotnet/roslyn/issues/40524) | [jcouv](https://github.com/jcouv) | TBD | [jcouv](https://github.com/jcouv) |
+| [Improved Definite Assignment](https://github.com/dotnet/csharplang/issues/4465) | [improved-definite-assignment](https://github.com/dotnet/roslyn/tree/features/improved-definite-assignment) | [In Progress](https://github.com/dotnet/roslyn/issues/51463) | [RikkiGibson](https://github.com/RikkiGibson) | [jcouv](https://github.com/jcouv) | [jaredpar](https://github.com/jaredpar) |
+| [Relax ordering of `ref` and `partial` modifiers](https://github.com/dotnet/csharplang/issues/946) | [ref-partial](https://github.com/dotnet/roslyn/tree/features/ref-partial) | In Progress | [alrz](https://github.com/alrz) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) |
+| [Parameter null-checking](https://github.com/dotnet/csharplang/issues/2145) | [param-nullchecking](https://github.com/dotnet/roslyn/tree/features/param-nullchecking) | [In Progress](https://github.com/dotnet/roslyn/issues/36024) | [fayrose](https://github.com/fayrose) | [agocke](https://github.com/agocke) | [jaredpar](https://github.com/jaredpar) |
+| [Caller expression attribute](https://github.com/dotnet/csharplang/issues/287) | [caller-expression](https://github.com/dotnet/roslyn/tree/features/caller-expression) | Prototype | [alrz](https://github.com/alrz) | [jcouv](https://github.com/jcouv) | [jcouv](https://github.com/jcouv) |
+| [Generic attributes](https://github.com/dotnet/csharplang/issues/124) | [generic-attributes](https://github.com/dotnet/roslyn/tree/features/generic-attributes) | [In Progress](https://github.com/dotnet/roslyn/issues/36285) | [AviAvni](https://github.com/AviAvni) | [agocke](https://github.com/agocke) | [mattwar](https://github.com/mattwar) |
+| [Default in deconstruction](https://github.com/dotnet/roslyn/pull/25562) | [decon-default](https://github.com/dotnet/roslyn/tree/features/decon-default) | [Implemented](https://github.com/dotnet/roslyn/issues/25559) | [jcouv](https://github.com/jcouv) | [gafter](https://github.com/gafter) | [jcouv](https://github.com/jcouv) |
+| [Constant Interpolated Strings](https://github.com/dotnet/csharplang/issues/2951) | master | [Merged into 16.9p3](https://github.com/dotnet/roslyn/pull/49676) | [kevinsun-dev](https://github.com/kevinsun-dev) | [333fred](https://github.com/333fred) | [jaredar](https://github.com/jaredpar), [agocke](https://github.com/agocke) |
+| [Mix declarations and variables in deconstruction](https://github.com/dotnet/csharplang/issues/125) | master | [Merged into 16.10](https://github.com/dotnet/roslyn/issues/47746) | [YairHalberstadt ](https://github.com/YairHalberstadt) | [jcouv](https://github.com/jcouv) | [MadsTorgersen](https://github.com/MadsTorgersen) |
| [List patterns](https://github.com/dotnet/csharplang/issues/3435) | [list-patterns](https://github.com/dotnet/roslyn/tree/features/list-patterns) | [In Progress](https://github.com/dotnet/roslyn/issues/51289) | [alrz](https://github.com/alrz) | [333fred](https://github.com/333fred) (tentative) | [333fred](https://github.com/333fred) |
# VB 16.9
-| Feature | Branch | State | Developers | Reviewer | LDM Champ |
-|----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------------|-----------------------------------------|
-| [Enable consumption of init-only properties](https://github.com/dotnet/roslyn/pull/50414) | master | [Merged (16.9p3)](https://github.com/dotnet/roslyn/issues/50792) | [AlekseyTs](https://github.com/AlekseyTs) | [jcouv](https://github.com/jcouv)
+| Feature | Branch | State | Developers | Reviewer | LDM Champ |
+|-------------------------------------------------------------------------------------------|--------|------------------------------------------------------------------|-------------------------------------------|-----------------------------------|-----------|
+| [Enable consumption of init-only properties](https://github.com/dotnet/roslyn/pull/50414) | master | [Merged (16.9p3)](https://github.com/dotnet/roslyn/issues/50792) | [AlekseyTs](https://github.com/AlekseyTs) | [jcouv](https://github.com/jcouv) | N/A |
# C# 9
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 148bd1902c0ed..c02e857ee30fd 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -7,9 +7,9 @@
https://github.com/dotnet/arcade
4957a6f3dd5f6fd1ca9ff06f9c50402f2e3b17e8
-
+
https://github.com/dotnet/roslyn
- 69f354dd21df8dac374c35169bdabb9000cfdea3
+ 686f13c61b1e26071ae89e107b0a3407a6b93a74
https://github.com/dotnet/arcade
diff --git a/eng/Versions.props b/eng/Versions.props
index 232567d6adb1d..d4c63bf331387 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -23,7 +23,7 @@
- 3.10.0-1.21113.12
+ 3.10.0-2.21122.2
@@ -32,7 +32,8 @@
1.0.1-beta1.20623.3
3.8.0
16.8.181
- 5.0.0-alpha1.19409.1
+ 5.0.0-alpha1.19409.1
+ 5.0.0-preview.1.20112.8
16.9.150
16.8.30406.65-pre
+
+
+
+
+ PreserveNewest
+ runtimes
+ false
+ false
+
+
+ PreserveNewest
+ runtimes
+ false
+ false
+
+
+ PreserveNewest
+ runtimes
+ false
+ false
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets
index 15b067deb0476..e33e38e1c82d5 100644
--- a/eng/targets/Imports.targets
+++ b/eng/targets/Imports.targets
@@ -46,6 +46,15 @@
-->
false
true
+
+
+ false
+ true
- false
-
enable
diff --git a/eng/test-rebuild.ps1 b/eng/test-rebuild.ps1
index 10b83f7ce4a73..5730b9d841f2b 100644
--- a/eng/test-rebuild.ps1
+++ b/eng/test-rebuild.ps1
@@ -6,6 +6,7 @@
param(
[string]$configuration = "Debug",
[switch]$ci = $false,
+ [switch]$noBuild = $false,
[switch]$help)
Set-StrictMode -version 2.0
@@ -15,6 +16,7 @@ function Print-Usage() {
Write-Host "Usage: test-rebuild.ps1"
Write-Host " -configuration Build configuration ('Debug' or 'Release')"
Write-Host " -ci Set when running on CI server"
+ Write-Host " -noBuild If set, skips running a bootstrap build before running the rebuild"
Write-Host " -help Print help and exit"
}
@@ -27,9 +29,54 @@ try {
. (Join-Path $PSScriptRoot "build-utils.ps1")
Push-Location $RepoRoot
- Write-Host "Building Roslyn"
- Exec-Console (Join-Path $PSScriptRoot "build.ps1") "-restore -build -ci:$ci -configuration:$configuration -pack -binaryLog"
- Exec-Console "artifacts\bin\BuildValidator\$configuration\net472\BuildValidator.exe" "--assembliesPath '$ArtifactsDir/obj/Microsoft.CodeAnalysis'"
+ if (-not $noBuild) {
+ Write-Host "Building Roslyn"
+ Exec-Block { & (Join-Path $PSScriptRoot "build.ps1") -build -bootstrap -ci:$ci -configuration:$configuration -pack -binaryLog }
+ }
+
+ $dotnetInstallDir = (InitializeDotNetCli -install:$true)
+ $rebuildArgs = ("--verbose" +
+ " --assembliesPath `"$ArtifactsDir/obj/AnalyzerRunner/$configuration/netcoreapp3.1`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/AnalyzerRunner/$configuration/net5.0`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/CodeStyleConfigFileGenerator`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/csc/$configuration/netcoreapp3.1`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/CSharpResultProvider.NetFX20`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/CSharpSyntaxGenerator`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/csi/$configuration/netcoreapp3.1`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/IdeCoreBenchmarks/$configuration/netcoreapp3.1`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/IdeCoreBenchmarks/$configuration/net5.0`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CodeStyle`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CodeStyle.Fixes`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.Compiler.Test.Resources`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CSharp`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CSharp.CodeStyle`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CSharp.ExpressionCompiler`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CSharp.Features`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.CSharp.Workspaces`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.EditorFeatures.Text`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.ExpressionCompiler`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.ExternalAccess.Debugger`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.ExternalAccess.Razor`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.Remote.Razor.ServiceHub`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.Remote.Workspaces`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.ResultProvider`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.Scripting`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.Scripting.TestUtilities`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.TestSourceGenerator`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.VisualBasic`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/Microsoft.CodeAnalysis.Workspaces`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/PrepareTests`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/RunTests`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/vbc/$configuration/netcoreapp3.1`"" +
+ " --assembliesPath `"$ArtifactsDir/obj/VBCSCompiler/$configuration/netcoreapp3.1`"" +
+
+ " --debugPath `"$ArtifactsDir/BuildValidator`"" +
+ " --sourcePath `"$RepoRoot`"" +
+ " --referencesPath `"$ArtifactsDir/bin`"" +
+ " --referencesPath `"$dotnetInstallDir/packs`"")
+ Exec-Console "$ArtifactsDir/bin/BuildValidator/$configuration/net472/BuildValidator.exe" $rebuildArgs
exit 0
}
diff --git a/scripts/merge-vs-deps.ps1 b/scripts/merge-vs-deps.ps1
index ef91539806527..37a9ba2fa61a1 100644
--- a/scripts/merge-vs-deps.ps1
+++ b/scripts/merge-vs-deps.ps1
@@ -1,4 +1,20 @@
-git pull origin master-vs-deps
+[CmdletBinding(PositionalBinding=$false)]
+Param(
+ [string]$userName,
+ [string]$userEmail,
+ [string]$accessToken = "")
+
+git config user.name $userName
+git config user.email $userEmail
+
+if ($accessToken -eq "") {
+ git pull origin master-vs-deps
+}
+else {
+ $base64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$accessToken"))
+ git -c http.extraheader="AUTHORIZATION: Basic $base64Pat" pull origin master-vs-deps
+}
+
if (-not $?)
{
Write-Host "##vso[task.logissue type=error]Failed to merge master-vs-deps into source branch"
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
index 05ed9d38f94c6..d1586fcb68699 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
@@ -155,6 +155,7 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
MethodSymbol? attributeConstructor = null;
// Bind attributeType's constructor based on the bound constructor arguments
+ ImmutableArray boundConstructorArguments;
if (!attributeTypeForBinding.IsErrorType())
{
attributeConstructor = BindAttributeConstructor(node,
@@ -165,8 +166,16 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
suppressErrors: attributeType.IsErrorType(),
ref argsToParamsOpt,
ref expanded,
- ref useSiteInfo);
+ ref useSiteInfo,
+ out boundConstructorArguments);
}
+ else
+ {
+ boundConstructorArguments = analyzedArguments.ConstructorArguments.Arguments.SelectAsArray(
+ static (arg, attributeArgumentBinder) => attributeArgumentBinder.BindToTypeForErrorRecovery(arg),
+ attributeArgumentBinder);
+ }
+ Debug.Assert(boundConstructorArguments.All(a => !a.NeedsToBeConverted()));
diagnostics.Add(node, useSiteInfo);
if (attributeConstructor is object)
@@ -179,11 +188,11 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
}
}
- var constructorArguments = analyzedArguments.ConstructorArguments;
- ImmutableArray boundConstructorArguments = constructorArguments.Arguments.ToImmutableAndFree();
- ImmutableArray boundConstructorArgumentNamesOpt = constructorArguments.GetNames();
- ImmutableArray boundNamedArguments = analyzedArguments.NamedArguments;
- constructorArguments.Free();
+ ImmutableArray boundConstructorArgumentNamesOpt = analyzedArguments.ConstructorArguments.GetNames();
+ ImmutableArray boundNamedArguments = analyzedArguments.NamedArguments?.ToImmutableAndFree() ?? ImmutableArray.Empty;
+ Debug.Assert(boundNamedArguments.All(arg => !arg.Right.NeedsToBeConverted()));
+
+ analyzedArguments.ConstructorArguments.Free();
return new BoundAttribute(node, attributeConstructor, boundConstructorArguments, boundConstructorArgumentNamesOpt, argsToParamsOpt, expanded,
boundNamedArguments, resultKind, attributeType, hasErrors: resultKind != LookupResultKind.Viable);
@@ -293,7 +302,7 @@ protected bool IsAttributeConditionallyOmitted(NamedTypeSymbol attributeType, Sy
}
///
- /// The result of this method captures some AnalyzedArguments, which must be free'ed by the caller.
+ /// The caller is responsible for freeing and .
///
private AnalyzedAttributeArguments BindAttributeArguments(
AttributeArgumentListSyntax? attributeArgumentList,
@@ -301,11 +310,10 @@ private AnalyzedAttributeArguments BindAttributeArguments(
BindingDiagnosticBag diagnostics)
{
var boundConstructorArguments = AnalyzedArguments.GetInstance();
- var boundNamedArguments = ImmutableArray.Empty;
+ ArrayBuilder? boundNamedArgumentsBuilder = null;
if (attributeArgumentList != null)
{
- ArrayBuilder? boundNamedArgumentsBuilder = null;
HashSet? boundNamedArgumentsSet = null;
// Only report the first "non-trailing named args required C# 7.2" error,
@@ -342,7 +350,7 @@ private AnalyzedAttributeArguments BindAttributeArguments(
string argumentName = argument.NameEquals.Name.Identifier.ValueText!;
if (boundNamedArgumentsBuilder == null)
{
- boundNamedArgumentsBuilder = ArrayBuilder.GetInstance();
+ boundNamedArgumentsBuilder = ArrayBuilder.GetInstance();
boundNamedArgumentsSet = new HashSet();
}
else if (boundNamedArgumentsSet!.Contains(argumentName))
@@ -351,22 +359,17 @@ private AnalyzedAttributeArguments BindAttributeArguments(
Error(diagnostics, ErrorCode.ERR_DuplicateNamedAttributeArgument, argument, argumentName);
}
- BoundExpression boundNamedArgument = BindNamedAttributeArgument(argument, attributeType, diagnostics);
+ BoundAssignmentOperator boundNamedArgument = BindNamedAttributeArgument(argument, attributeType, diagnostics);
boundNamedArgumentsBuilder.Add(boundNamedArgument);
boundNamedArgumentsSet.Add(argumentName);
}
}
-
- if (boundNamedArgumentsBuilder != null)
- {
- boundNamedArguments = boundNamedArgumentsBuilder.ToImmutableAndFree();
- }
}
- return new AnalyzedAttributeArguments(boundConstructorArguments, boundNamedArguments);
+ return new AnalyzedAttributeArguments(boundConstructorArguments, boundNamedArgumentsBuilder);
}
- private BoundExpression BindNamedAttributeArgument(AttributeArgumentSyntax namedArgument, NamedTypeSymbol attributeType, BindingDiagnosticBag diagnostics)
+ private BoundAssignmentOperator BindNamedAttributeArgument(AttributeArgumentSyntax namedArgument, NamedTypeSymbol attributeType, BindingDiagnosticBag diagnostics)
{
bool wasError;
LookupResultKind resultKind;
@@ -537,7 +540,8 @@ protected MethodSymbol BindAttributeConstructor(
bool suppressErrors,
ref ImmutableArray argsToParamsOpt,
ref bool expanded,
- ref CompoundUseSiteInfo useSiteInfo)
+ ref CompoundUseSiteInfo useSiteInfo,
+ out ImmutableArray constructorArguments)
{
MemberResolutionResult memberResolutionResult;
ImmutableArray candidateConstructors;
@@ -556,6 +560,11 @@ protected MethodSymbol BindAttributeConstructor(
memberResolutionResult.IsValid && !IsConstructorAccessible(memberResolutionResult.Member, ref useSiteInfo) ?
LookupResultKind.Inaccessible :
LookupResultKind.OverloadResolutionFailure);
+ constructorArguments = BuildArgumentsForErrorRecovery(boundConstructorArguments, candidateConstructors);
+ }
+ else
+ {
+ constructorArguments = boundConstructorArguments.Arguments.ToImmutable();
}
argsToParamsOpt = memberResolutionResult.Result.ArgsToParamsOpt;
expanded = memberResolutionResult.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm;
@@ -982,7 +991,7 @@ public ImmutableArray VisitArguments(ImmutableArray> VisitNamedArguments(ImmutableArray arguments, BindingDiagnosticBag diagnostics, ref bool attrHasErrors)
+ public ImmutableArray> VisitNamedArguments(ImmutableArray arguments, BindingDiagnosticBag diagnostics, ref bool attrHasErrors)
{
ArrayBuilder>? builder = null;
foreach (var argument in arguments)
@@ -1008,28 +1017,20 @@ public ImmutableArray> VisitNamedArguments(I
return builder.ToImmutableAndFree();
}
- private KeyValuePair? VisitNamedArgument(BoundExpression argument, BindingDiagnosticBag diagnostics, ref bool attrHasErrors)
+ private KeyValuePair? VisitNamedArgument(BoundAssignmentOperator assignment, BindingDiagnosticBag diagnostics, ref bool attrHasErrors)
{
KeyValuePair? visitedArgument = null;
- switch (argument.Kind)
+ switch (assignment.Left.Kind)
{
- case BoundKind.AssignmentOperator:
- var assignment = (BoundAssignmentOperator)argument;
-
- switch (assignment.Left.Kind)
- {
- case BoundKind.FieldAccess:
- var fa = (BoundFieldAccess)assignment.Left;
- visitedArgument = new KeyValuePair(fa.FieldSymbol.Name, VisitExpression(assignment.Right, diagnostics, ref attrHasErrors, argument.HasAnyErrors));
- break;
-
- case BoundKind.PropertyAccess:
- var pa = (BoundPropertyAccess)assignment.Left;
- visitedArgument = new KeyValuePair(pa.PropertySymbol.Name, VisitExpression(assignment.Right, diagnostics, ref attrHasErrors, argument.HasAnyErrors));
- break;
- }
+ case BoundKind.FieldAccess:
+ var fa = (BoundFieldAccess)assignment.Left;
+ visitedArgument = new KeyValuePair(fa.FieldSymbol.Name, VisitExpression(assignment.Right, diagnostics, ref attrHasErrors, assignment.HasAnyErrors));
+ break;
+ case BoundKind.PropertyAccess:
+ var pa = (BoundPropertyAccess)assignment.Left;
+ visitedArgument = new KeyValuePair(pa.PropertySymbol.Name, VisitExpression(assignment.Right, diagnostics, ref attrHasErrors, assignment.HasAnyErrors));
break;
}
@@ -1248,9 +1249,9 @@ private static TypedConstant CreateTypedConstant(BoundExpression node, TypedCons
private struct AnalyzedAttributeArguments
{
internal readonly AnalyzedArguments ConstructorArguments;
- internal readonly ImmutableArray NamedArguments;
+ internal readonly ArrayBuilder? NamedArguments;
- internal AnalyzedAttributeArguments(AnalyzedArguments constructorArguments, ImmutableArray namedArguments)
+ internal AnalyzedAttributeArguments(AnalyzedArguments constructorArguments, ArrayBuilder? namedArguments)
{
this.ConstructorArguments = constructorArguments;
this.NamedArguments = namedArguments;
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
index ef39b472be66e..1ccd722dbbb72 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
@@ -59,6 +59,7 @@ private static ImmutableArray GetOriginalMethods(OverloadResolutio
return builder.ToImmutableAndFree();
}
+#nullable enable
///
/// Helper method to create a synthesized method invocation expression.
///
@@ -81,7 +82,7 @@ internal BoundExpression MakeInvocationExpression(
BindingDiagnosticBag diagnostics,
SeparatedSyntaxList typeArgsSyntax = default(SeparatedSyntaxList),
ImmutableArray typeArgs = default(ImmutableArray),
- CSharpSyntaxNode queryClause = null,
+ CSharpSyntaxNode? queryClause = null,
bool allowFieldsAndProperties = false,
bool allowUnexpandedForm = true)
{
@@ -141,6 +142,7 @@ internal BoundExpression MakeInvocationExpression(
analyzedArguments.Free();
return result;
}
+#nullable disable
///
/// Bind an expression as a method invocation.
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
index 0f9ece1fc4f05..40591d3932cc3 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
@@ -1615,7 +1615,7 @@
-
+
diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs
index 8f5be8db406c3..ab4a498be4c80 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs
@@ -73,7 +73,7 @@ internal partial class BoundAnonymousObjectCreationExpression
internal partial class BoundAttribute
{
- protected override ImmutableArray Children => StaticCast.From(this.ConstructorArguments.AddRange(this.NamedArguments));
+ protected override ImmutableArray Children => StaticCast.From(this.ConstructorArguments.AddRange(StaticCast.From(this.NamedArguments)));
}
internal partial class BoundQueryClause
diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
index 1423b578476ef..680d8ad611fea 100644
--- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs
@@ -5756,7 +5756,7 @@ public BoundEventAssignmentOperator Update(EventSymbol @event, bool isAddition,
internal sealed partial class BoundAttribute : BoundExpression
{
- public BoundAttribute(SyntaxNode syntax, MethodSymbol? constructor, ImmutableArray constructorArguments, ImmutableArray constructorArgumentNamesOpt, ImmutableArray constructorArgumentsToParamsOpt, bool constructorExpanded, ImmutableArray namedArguments, LookupResultKind resultKind, TypeSymbol type, bool hasErrors = false)
+ public BoundAttribute(SyntaxNode syntax, MethodSymbol? constructor, ImmutableArray constructorArguments, ImmutableArray constructorArgumentNamesOpt, ImmutableArray constructorArgumentsToParamsOpt, bool constructorExpanded, ImmutableArray namedArguments, LookupResultKind resultKind, TypeSymbol type, bool hasErrors = false)
: base(BoundKind.Attribute, syntax, type, hasErrors || constructorArguments.HasErrors() || namedArguments.HasErrors())
{
@@ -5786,14 +5786,14 @@ public BoundAttribute(SyntaxNode syntax, MethodSymbol? constructor, ImmutableArr
public bool ConstructorExpanded { get; }
- public ImmutableArray NamedArguments { get; }
+ public ImmutableArray NamedArguments { get; }
private readonly LookupResultKind _ResultKind;
public override LookupResultKind ResultKind { get { return _ResultKind; } }
[DebuggerStepThrough]
public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitAttribute(this);
- public BoundAttribute Update(MethodSymbol? constructor, ImmutableArray constructorArguments, ImmutableArray constructorArgumentNamesOpt, ImmutableArray constructorArgumentsToParamsOpt, bool constructorExpanded, ImmutableArray namedArguments, LookupResultKind resultKind, TypeSymbol type)
+ public BoundAttribute Update(MethodSymbol? constructor, ImmutableArray constructorArguments, ImmutableArray constructorArgumentNamesOpt, ImmutableArray constructorArgumentsToParamsOpt, bool constructorExpanded, ImmutableArray namedArguments, LookupResultKind resultKind, TypeSymbol type)
{
if (!Symbols.SymbolEqualityComparer.ConsiderEverything.Equals(constructor, this.Constructor) || constructorArguments != this.ConstructorArguments || constructorArgumentNamesOpt != this.ConstructorArgumentNamesOpt || constructorArgumentsToParamsOpt != this.ConstructorArgumentsToParamsOpt || constructorExpanded != this.ConstructorExpanded || namedArguments != this.NamedArguments || resultKind != this.ResultKind || !TypeSymbol.Equals(type, this.Type, TypeCompareKind.ConsiderEverything))
{
@@ -10526,7 +10526,7 @@ internal abstract partial class BoundTreeRewriter : BoundTreeVisitor
public override BoundNode? VisitAttribute(BoundAttribute node)
{
ImmutableArray constructorArguments = this.VisitList(node.ConstructorArguments);
- ImmutableArray namedArguments = this.VisitList(node.NamedArguments);
+ ImmutableArray namedArguments = this.VisitList(node.NamedArguments);
TypeSymbol? type = this.VisitType(node.Type);
return node.Update(node.Constructor, constructorArguments, node.ConstructorArgumentNamesOpt, node.ConstructorArgumentsToParamsOpt, node.ConstructorExpanded, namedArguments, node.ResultKind, type);
}
@@ -12407,7 +12407,7 @@ public NullabilityRewriter(ImmutableDictionary constructorArguments = this.VisitList(node.ConstructorArguments);
- ImmutableArray namedArguments = this.VisitList(node.NamedArguments);
+ ImmutableArray namedArguments = this.VisitList(node.NamedArguments);
BoundAttribute updatedNode;
if (_updatedNullabilities.TryGetValue(node, out (NullabilityInfo Info, TypeSymbol? Type) infoAndType))
diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
index 7096e1231aece..0a5fa9815f2d9 100644
--- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
@@ -96,7 +96,7 @@ private set
internal BoundExpression MakeInvocationExpression(
BinderFlags flags,
SyntaxNode node,
- BoundExpression? receiver,
+ BoundExpression receiver,
string methodName,
ImmutableArray args,
BindingDiagnosticBag diagnostics,
@@ -657,12 +657,12 @@ public BoundExpression MakeIsNotANumberTest(BoundExpression input)
}
}
- public BoundExpression InstanceCall(BoundExpression? receiver, string name, BoundExpression arg)
+ public BoundExpression InstanceCall(BoundExpression receiver, string name, BoundExpression arg)
{
return MakeInvocationExpression(BinderFlags.None, this.Syntax, receiver, name, ImmutableArray.Create(arg), this.Diagnostics);
}
- public BoundExpression InstanceCall(BoundExpression? receiver, string name)
+ public BoundExpression InstanceCall(BoundExpression receiver, string name)
{
return MakeInvocationExpression(BinderFlags.None, this.Syntax, receiver, name, ImmutableArray.Empty, this.Diagnostics);
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs
index 6467b5d32c121..378deff3457b5 100644
--- a/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs
@@ -311,6 +311,8 @@ INamedTypeSymbol IMethodSymbol.AssociatedAnonymousDelegate
bool IMethodSymbol.IsExtensionMethod => _underlying.IsExtensionMethod;
+ System.Reflection.MethodImplAttributes IMethodSymbol.MethodImplementationFlags => _underlying.ImplementationAttributes;
+
bool IMethodSymbol.IsVararg => _underlying.IsVararg;
bool IMethodSymbol.IsCheckedBuiltin => _underlying.IsCheckedBuiltin;
diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
index d615fae84c766..fd2c313e1b886 100644
--- a/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/TypeWithAnnotations.cs
@@ -942,8 +942,6 @@ private TypeSymbol GetResolvedType()
{
if ((object)_resolved == null)
{
- Debug.Assert(_underlying.IsSafeToResolve());
-
TryForceResolve(asValueType: _underlying.Type.IsValueType);
}
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs
index 8b1f8f242b7a5..5c97040f8c82a 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs
@@ -4,6 +4,8 @@
#nullable disable
+using System.Linq;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
@@ -4871,6 +4873,384 @@ public class B
// [My(1 switch { 1 => 1, _ => string.Empty })]
Diagnostic(ErrorCode.ERR_BadArgType, "1 switch { 1 => 1, _ => string.Empty }").WithArguments("1", "", "int").WithLocation(11, 9)
);
+
+ var tree = compilation.SyntaxTrees[0];
+ var model = compilation.GetSemanticModel(tree);
+
+ var switchExpressions = tree.GetRoot().DescendantNodes().OfType().ToArray();
+
+ VerifyOperationTreeForNode(compilation, model, switchExpressions[0], @"
+ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch { ... 1, _ => 2 }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => 2')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
+");
+
+ VerifyOperationTreeForNode(compilation, model, switchExpressions[1], @"
+ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch { ... > new B() }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => new A()')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 A.op_Implicit(A a)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new A()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 A.op_Implicit(A a))
+ Operand:
+ IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A, IsInvalid) (Syntax: 'new A()')
+ Arguments(0)
+ Initializer:
+ null
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => new B()')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 B.op_Implicit(B b)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new B()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 B.op_Implicit(B b))
+ Operand:
+ IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B, IsInvalid) (Syntax: 'new B()')
+ Arguments(0)
+ Initializer:
+ null
+");
+
+ VerifyOperationTreeForNode(compilation, model, switchExpressions[2], @"
+ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: ?, IsInvalid) (Syntax: '1 switch { ... ing.Empty }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: '1')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => string.Empty')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: 'string.Empty')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String, IsInvalid) (Syntax: 'string.Empty')
+ Instance Receiver:
+ null
+");
+ }
+
+ [Fact]
+ public void TargetTypedSwitch_Attribute_NamedArgument()
+ {
+ var source = @"
+using System;
+class Program
+{
+ [My(Value = 1 switch { 1 => 1, _ => 2 })]
+ public static void M1() { }
+
+ [My(Value = 1 switch { 1 => new A(), _ => new B() })]
+ public static void M2() { }
+
+ [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
+ public static void M3() { }
+}
+public class MyAttribute : Attribute
+{
+ public MyAttribute() { }
+ public int Value { get; set; }
+}
+public class A
+{
+ public static implicit operator int(A a) => 4;
+}
+public class B
+{
+ public static implicit operator int(B b) => 2;
+}
+";
+ var compilation = CreateCompilation(source);
+ compilation.VerifyDiagnostics(
+ // (5,17): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
+ // [My(Value = 1 switch { 1 => 1, _ => 2 })]
+ Diagnostic(ErrorCode.ERR_BadAttributeArgument, "1 switch { 1 => 1, _ => 2 }").WithLocation(5, 17),
+ // (8,17): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
+ // [My(Value = 1 switch { 1 => new A(), _ => new B() })]
+ Diagnostic(ErrorCode.ERR_BadAttributeArgument, "1 switch { 1 => new A(), _ => new B() }").WithLocation(8, 17),
+ // (11,41): error CS0029: Cannot implicitly convert type 'string' to 'int'
+ // [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
+ Diagnostic(ErrorCode.ERR_NoImplicitConv, "string.Empty").WithArguments("string", "int").WithLocation(11, 41)
+ );
+
+ var tree = compilation.SyntaxTrees[0];
+ var model = compilation.GetSemanticModel(tree);
+
+ var attributeArguments = tree.GetRoot().DescendantNodes().OfType().ToArray();
+
+ VerifyOperationTreeForNode(compilation, model, attributeArguments[0], @"
+ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Value = 1 s ... 1, _ => 2 }')
+ Left:
+ IPropertyReferenceOperation: System.Int32 MyAttribute.Value { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Value')
+ Instance Receiver:
+ null
+ Right:
+ ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch { ... 1, _ => 2 }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => 2')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
+");
+
+ VerifyOperationTreeForNode(compilation, model, attributeArguments[1], @"
+ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Value = 1 s ... > new B() }')
+ Left:
+ IPropertyReferenceOperation: System.Int32 MyAttribute.Value { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Value')
+ Instance Receiver:
+ null
+ Right:
+ ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch { ... > new B() }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => new A()')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 A.op_Implicit(A a)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new A()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 A.op_Implicit(A a))
+ Operand:
+ IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A, IsInvalid) (Syntax: 'new A()')
+ Arguments(0)
+ Initializer:
+ null
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => new B()')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 B.op_Implicit(B b)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new B()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 B.op_Implicit(B b))
+ Operand:
+ IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B, IsInvalid) (Syntax: 'new B()')
+ Arguments(0)
+ Initializer:
+ null
+");
+
+ VerifyOperationTreeForNode(compilation, model, attributeArguments[2], @"
+ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Value = 1 s ... ing.Empty }')
+ Left:
+ IPropertyReferenceOperation: System.Int32 MyAttribute.Value { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Value')
+ Instance Receiver:
+ null
+ Right:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: '1 switch { ... ing.Empty }')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: ?, IsInvalid) (Syntax: '1 switch { ... ing.Empty }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => 1')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => string.Empty')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: 'string.Empty')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String, IsInvalid) (Syntax: 'string.Empty')
+ Instance Receiver:
+ null
+");
+ }
+
+ [Fact]
+ public void TargetTypedSwitch_Attribute_MissingNamedArgument()
+ {
+ var source = @"
+using System;
+class Program
+{
+ [My(Value = 1 switch { 1 => 1, _ => 2 })]
+ public static void M1() { }
+
+ [My(Value = 1 switch { 1 => new A(), _ => new B() })]
+ public static void M2() { }
+
+ [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
+ public static void M3() { }
+}
+public class MyAttribute : Attribute
+{
+ public MyAttribute() { }
+}
+public class A
+{
+ public static implicit operator int(A a) => 4;
+}
+public class B
+{
+ public static implicit operator int(B b) => 2;
+}
+";
+ var compilation = CreateCompilation(source);
+ compilation.VerifyDiagnostics(
+ // (5,9): error CS0246: The type or namespace name 'Value' could not be found (are you missing a using directive or an assembly reference?)
+ // [My(Value = 1 switch { 1 => 1, _ => 2 })]
+ Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Value").WithArguments("Value").WithLocation(5, 9),
+ // (8,9): error CS0246: The type or namespace name 'Value' could not be found (are you missing a using directive or an assembly reference?)
+ // [My(Value = 1 switch { 1 => new A(), _ => new B() })]
+ Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Value").WithArguments("Value").WithLocation(8, 9),
+ // (11,9): error CS0246: The type or namespace name 'Value' could not be found (are you missing a using directive or an assembly reference?)
+ // [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
+ Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Value").WithArguments("Value").WithLocation(11, 9)
+ );
+
+ var tree = compilation.SyntaxTrees[0];
+ var model = compilation.GetSemanticModel(tree);
+
+ var attributeArguments = tree.GetRoot().DescendantNodes().OfType().ToArray();
+
+ VerifyOperationTreeForNode(compilation, model, attributeArguments[0], @"
+ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'Value = 1 s ... 1, _ => 2 }')
+ Left:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Value')
+ Children(0)
+ Right:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1 switch { ... 1, _ => 2 }')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32) (Syntax: '1 switch { ... 1, _ => 2 }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => 1')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '_ => 2')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
+");
+
+ VerifyOperationTreeForNode(compilation, model, attributeArguments[1], @"
+ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'Value = 1 s ... > new B() }')
+ Left:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Value')
+ Children(0)
+ Right:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1 switch { ... > new B() }')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: ?) (Syntax: '1 switch { ... > new B() }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => new A()')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: 'new A()')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A) (Syntax: 'new A()')
+ Arguments(0)
+ Initializer:
+ null
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '_ => new B()')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: 'new B()')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B) (Syntax: 'new B()')
+ Arguments(0)
+ Initializer:
+ null
+");
+
+ VerifyOperationTreeForNode(compilation, model, attributeArguments[2], @"
+ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'Value = 1 s ... ing.Empty }')
+ Left:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Value')
+ Children(0)
+ Right:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1 switch { ... ing.Empty }')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: ?) (Syntax: '1 switch { ... ing.Empty }')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Arms(2):
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => 1')
+ Pattern:
+ IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '_ => string.Empty')
+ Pattern:
+ IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
+ Value:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: 'string.Empty')
+ Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Operand:
+ IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String) (Syntax: 'string.Empty')
+ Instance Receiver:
+ null
+");
}
[Fact]
diff --git a/src/Compilers/CSharp/Test/Emit/Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj b/src/Compilers/CSharp/Test/Emit/Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj
index 85d2492702f27..263273fa60cbc 100644
--- a/src/Compilers/CSharp/Test/Emit/Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj
+++ b/src/Compilers/CSharp/Test/Emit/Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj
@@ -30,5 +30,5 @@
-
+
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConditionalAccessExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConditionalAccessExpression.cs
index 957c6f4012e1d..dcf4952a800bb 100644
--- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConditionalAccessExpression.cs
+++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IConditionalAccessExpression.cs
@@ -1563,5 +1563,189 @@ void M(C c)
Statements (0)
", DiagnosticDescription.None);
}
+
+ [Fact]
+ public void InvalidConditionalAccess_01()
+ {
+ var code = @"
+class C
+{
+ void M()
+ /**/{
+ _ = 123?[1, 2];
+ }/**/
+}
+";
+
+ var expectedDiagnostics = new[]
+ {
+ // file.cs(6,16): error CS0023: Operator '?' cannot be applied to operand of type 'int'
+ // _ = 123?[1, 2];
+ Diagnostic(ErrorCode.ERR_BadUnaryOp, "?").WithArguments("?", "int").WithLocation(6, 16)
+ };
+
+ VerifyFlowGraphAndDiagnosticsForTest(code, @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1} {R2}
+.locals {R1}
+{
+ CaptureIds: [0]
+ .locals {R2}
+ {
+ CaptureIds: [1] [2] [3]
+ Block[B1] - Block
+ Predecessors: [B0]
+ Statements (3)
+ IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '1')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '2')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
+ IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: '123')
+ Value:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: '123')
+ Children(1):
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 123, IsInvalid) (Syntax: '123')
+ Jump if True (Regular) to Block[B3]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: '123')
+ Operand:
+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: ?, IsInvalid, IsImplicit) (Syntax: '123')
+ Leaving: {R2}
+ Next (Regular) Block[B2]
+ Block[B2] - Block
+ Predecessors: [B1]
+ Statements (1)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: '[1, 2]')
+ Value:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: '[1, 2]')
+ Children(3):
+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: '1')
+ IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: '2')
+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: ?, IsInvalid, IsImplicit) (Syntax: '123')
+ Next (Regular) Block[B4]
+ Leaving: {R2}
+ }
+ Block[B3] - Block
+ Predecessors: [B1]
+ Statements (1)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: '123')
+ Value:
+ IDefaultValueOperation (OperationKind.DefaultValue, Type: ?, Constant: null, IsInvalid, IsImplicit) (Syntax: '123')
+ Next (Regular) Block[B4]
+ Block[B4] - Block
+ Predecessors: [B2] [B3]
+ Statements (1)
+ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: '_ = 123?[1, 2];')
+ Expression:
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: '_ = 123?[1, 2]')
+ Left:
+ IDiscardOperation (Symbol: ? _) (OperationKind.Discard, Type: ?) (Syntax: '_')
+ Right:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: ?, IsInvalid, IsImplicit) (Syntax: '123?[1, 2]')
+ Next (Regular) Block[B5]
+ Leaving: {R1}
+}
+Block[B5] - Exit
+ Predecessors: [B4]
+ Statements (0)
+", expectedDiagnostics);
+ }
+
+ [Fact]
+ public void InvalidConditionalAccess_02()
+ {
+ var code = @"
+class C
+{
+ void M()
+ /**/{
+ _ = 123?[1, 2].ToString();
+ }/**/
+}
+";
+
+ var expectedDiagnostics = new[]
+ {
+ // file.cs(6,16): error CS0023: Operator '?' cannot be applied to operand of type 'int'
+ // _ = 123?[1, 2];
+ Diagnostic(ErrorCode.ERR_BadUnaryOp, "?").WithArguments("?", "int").WithLocation(6, 16)
+ };
+
+ VerifyFlowGraphAndDiagnosticsForTest(code, @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1} {R2}
+.locals {R1}
+{
+ CaptureIds: [0]
+ .locals {R2}
+ {
+ CaptureIds: [1] [2] [3]
+ Block[B1] - Block
+ Predecessors: [B0]
+ Statements (3)
+ IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '1')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: '2')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
+ IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: '123')
+ Value:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid, IsImplicit) (Syntax: '123')
+ Children(1):
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 123, IsInvalid) (Syntax: '123')
+ Jump if True (Regular) to Block[B3]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: '123')
+ Operand:
+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: ?, IsInvalid, IsImplicit) (Syntax: '123')
+ Leaving: {R2}
+ Next (Regular) Block[B2]
+ Block[B2] - Block
+ Predecessors: [B1]
+ Statements (1)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: '[1, 2].ToString()')
+ Value:
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: '[1, 2].ToString()')
+ Children(1):
+ IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: '[1, 2].ToString')
+ Children(1):
+ IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: '[1, 2]')
+ Children(3):
+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: '1')
+ IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: '2')
+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: ?, IsInvalid, IsImplicit) (Syntax: '123')
+ Next (Regular) Block[B4]
+ Leaving: {R2}
+ }
+ Block[B3] - Block
+ Predecessors: [B1]
+ Statements (1)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: '123')
+ Value:
+ IDefaultValueOperation (OperationKind.DefaultValue, Type: ?, Constant: null, IsInvalid, IsImplicit) (Syntax: '123')
+ Next (Regular) Block[B4]
+ Block[B4] - Block
+ Predecessors: [B2] [B3]
+ Statements (1)
+ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: '_ = 123?[1, ... ToString();')
+ Expression:
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: '_ = 123?[1, ... .ToString()')
+ Left:
+ IDiscardOperation (Symbol: ? _) (OperationKind.Discard, Type: ?) (Syntax: '_')
+ Right:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: ?, IsInvalid, IsImplicit) (Syntax: '123?[1, 2].ToString()')
+ Next (Regular) Block[B5]
+ Leaving: {R1}
+}
+Block[B5] - Exit
+ Predecessors: [B4]
+ Statements (0)
+", expectedDiagnostics);
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs
index d778c6e6dcb36..fc94252b95daf 100644
--- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs
+++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs
@@ -15183,5 +15183,135 @@ static void F(A a)
Predecessors: [B3]
Statements (0)");
}
+
+ [Fact]
+ public void IndexedPropertyWithDefaultArgumentInVB()
+ {
+ var source1 =
+@"Imports System
+Imports System.Collections.Generic
+Imports System.Runtime.InteropServices
+
+
+
+
+
+Public Interface IA
+ Property P1(Optional index As Integer = 1) As Object
+ ReadOnly Property P2(Optional index As Integer = 2) As IA
+End Interface
+Public Class A
+ Implements IA
+ Property P1(Optional index As Integer = 1) As Object Implements IA.P1
+ Get
+ Return Nothing
+ End Get
+ Set(value As Object)
+ End Set
+ End Property
+ ReadOnly Property P2(Optional index As Integer = 2) As IA Implements IA.P2
+ Get
+ Return New A()
+ End Get
+ End Property
+End Class";
+ var reference1 = BasicCompilationUtils.CompileToMetadata(source1, verify: Verification.Passes);
+ var source2 =
+@"class B
+{
+ static void M(IA a)
+ /**/{
+ a = new IA() { P2 = { P1 = 5 } };
+ }/**/
+}";
+
+ VerifyFlowGraphAndDiagnosticsForTest(source2, expectedDiagnostics: DiagnosticDescription.None, references: new[] { reference1 },
+ expectedFlowGraph: @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1}
+.locals {R1}
+{
+ CaptureIds: [0] [1]
+ Block[B1] - Block
+ Predecessors: [B0]
+ Statements (2)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
+ Value:
+ IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: IA) (Syntax: 'a')
+ IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'new IA() { ... P1 = 5 } }')
+ Value:
+ IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: IA) (Syntax: 'new IA() { ... P1 = 5 } }')
+ Arguments(0)
+ Initializer:
+ null
+ Next (Regular) Block[B2]
+ Entering: {R2}
+ .locals {R2}
+ {
+ CaptureIds: [2]
+ Block[B2] - Block
+ Predecessors: [B1]
+ Statements (1)
+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'P2')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: 'P2')
+ Next (Regular) Block[B3]
+ Entering: {R3}
+ .locals {R3}
+ {
+ CaptureIds: [3]
+ Block[B3] - Block
+ Predecessors: [B2]
+ Statements (2)
+ IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'P1')
+ Value:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: 'P1')
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object) (Syntax: 'P1 = 5')
+ Left:
+ IPropertyReferenceOperation: System.Object IA.P1[[System.Int32 index = 1]] { get; set; } (OperationKind.PropertyReference, Type: System.Object) (Syntax: 'P1')
+ Instance Receiver:
+ IPropertyReferenceOperation: IA IA.P2[[System.Int32 index = 2]] { get; } (OperationKind.PropertyReference, Type: IA) (Syntax: 'P2')
+ Instance Receiver:
+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: IA, IsImplicit) (Syntax: 'new IA() { ... P1 = 5 } }')
+ Arguments(1):
+ IArgumentOperation (ArgumentKind.DefaultValue, Matching Parameter: index) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'P2')
+ IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: 'P2')
+ InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Arguments(1):
+ IArgumentOperation (ArgumentKind.DefaultValue, Matching Parameter: index) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'P1')
+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: 'P1')
+ InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ Right:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '5')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ (Boxing)
+ Operand:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 5) (Syntax: '5')
+ Next (Regular) Block[B4]
+ Leaving: {R3} {R2}
+ }
+ }
+ Block[B4] - Block
+ Predecessors: [B3]
+ Statements (1)
+ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a = new IA( ... P1 = 5 } };')
+ Expression:
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: IA) (Syntax: 'a = new IA( ... P1 = 5 } }')
+ Left:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: IA, IsImplicit) (Syntax: 'a')
+ Right:
+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: IA, IsImplicit) (Syntax: 'new IA() { ... P1 = 5 } }')
+ Next (Regular) Block[B5]
+ Leaving: {R1}
+}
+Block[B5] - Exit
+ Predecessors: [B4]
+ Statements (0)
+");
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs
index 9875cf6aa07a0..77d4298dd2c41 100644
--- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs
+++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs
@@ -8487,5 +8487,486 @@ void M()
Statements (0)
");
}
+
+ [Fact]
+ public void UsingDeclaration_InsideSwitchCaseEmbeddedStatements()
+ {
+ var source = @"
+using System;
+class C1 : IDisposable
+{
+ public void Dispose() { }
+}
+class C2
+{
+ public static void M(int x)
+ /**/{
+ switch (x)
+ {
+ case 5:
+ using C1 o1 = new C1();
+ break;
+ }
+ }/**/
+}";
+
+ var expectedDiagnostics = new DiagnosticDescription[] {
+ // file.cs(14,17): error CS8647: A using variable cannot be used directly within a switch section (consider using braces).
+ // using C1 o1 = new C1();
+ Diagnostic(ErrorCode.ERR_UsingVarInSwitchCase, "using C1 o1 = new C1();").WithLocation(14, 17)
+ };
+
+ var expectedFlowGraph = @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1}
+.locals {R1}
+{
+ CaptureIds: [0]
+ Block[B1] - Block
+ Predecessors: [B0]
+ Statements (1)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'x')
+ Value:
+ IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x')
+ Next (Regular) Block[B2]
+ Entering: {R2}
+ .locals {R2}
+ {
+ Locals: [C1 o1]
+ Block[B2] - Block
+ Predecessors: [B1]
+ Statements (0)
+ Jump if False (Regular) to Block[B8]
+ IBinaryOperation (BinaryOperatorKind.Equals) (OperationKind.Binary, Type: System.Boolean, IsImplicit) (Syntax: '5')
+ Left:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'x')
+ Right:
+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 5) (Syntax: '5')
+ Leaving: {R2} {R1}
+ Next (Regular) Block[B3]
+ Block[B3] - Block
+ Predecessors: [B2]
+ Statements (1)
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Left:
+ ILocalReferenceOperation: o1 (IsDeclaration: True) (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Right:
+ IObjectCreationOperation (Constructor: C1..ctor()) (OperationKind.ObjectCreation, Type: C1, IsInvalid) (Syntax: 'new C1()')
+ Arguments(0)
+ Initializer:
+ null
+ Next (Regular) Block[B4]
+ Entering: {R3} {R4}
+ .try {R3, R4}
+ {
+ Block[B4] - Block
+ Predecessors: [B3]
+ Statements (0)
+ Next (Regular) Block[B8]
+ Finalizing: {R5}
+ Leaving: {R4} {R3} {R2} {R1}
+ }
+ .finally {R5}
+ {
+ Block[B5] - Block
+ Predecessors (0)
+ Statements (0)
+ Jump if True (Regular) to Block[B7]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Next (Regular) Block[B6]
+ Block[B6] - Block
+ Predecessors: [B5]
+ Statements (1)
+ IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Instance Receiver:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
+ (ImplicitReference)
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Arguments(0)
+ Next (Regular) Block[B7]
+ Block[B7] - Block
+ Predecessors: [B5] [B6]
+ Statements (0)
+ Next (StructuredExceptionHandling) Block[null]
+ }
+ }
+}
+Block[B8] - Exit
+ Predecessors: [B2] [B4]
+ Statements (0)
+";
+
+ VerifyFlowGraphAndDiagnosticsForTest(source, expectedFlowGraph, expectedDiagnostics);
+ }
+
+ [Fact]
+ public void UsingDeclaration_InsideIfEmbeddedStatement()
+ {
+ var source = @"
+using System;
+class C1 : IDisposable
+{
+ public void Dispose() { }
+}
+class C2
+{
+ public static void M(bool b)
+ /**/{
+ if (b)
+ using C1 o1 = new C1();
+ }/**/
+}";
+
+ var expectedDiagnostics = new DiagnosticDescription[] {
+ // file.cs(12,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
+ // using C1 o1 = new C1();
+ Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "using C1 o1 = new C1();").WithLocation(12, 13)
+ };
+
+ var expectedFlowGraph = @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+Block[B1] - Block
+ Predecessors: [B0]
+ Statements (0)
+ Jump if False (Regular) to Block[B7]
+ IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b')
+ Next (Regular) Block[B2]
+ Entering: {R1}
+.locals {R1}
+{
+ Locals: [C1 o1]
+ Block[B2] - Block
+ Predecessors: [B1]
+ Statements (1)
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Left:
+ ILocalReferenceOperation: o1 (IsDeclaration: True) (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Right:
+ IObjectCreationOperation (Constructor: C1..ctor()) (OperationKind.ObjectCreation, Type: C1, IsInvalid) (Syntax: 'new C1()')
+ Arguments(0)
+ Initializer:
+ null
+ Next (Regular) Block[B3]
+ Entering: {R2} {R3}
+ .try {R2, R3}
+ {
+ Block[B3] - Block
+ Predecessors: [B2]
+ Statements (0)
+ Next (Regular) Block[B7]
+ Finalizing: {R4}
+ Leaving: {R3} {R2} {R1}
+ }
+ .finally {R4}
+ {
+ Block[B4] - Block
+ Predecessors (0)
+ Statements (0)
+ Jump if True (Regular) to Block[B6]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Next (Regular) Block[B5]
+ Block[B5] - Block
+ Predecessors: [B4]
+ Statements (1)
+ IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Instance Receiver:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
+ (ImplicitReference)
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Arguments(0)
+ Next (Regular) Block[B6]
+ Block[B6] - Block
+ Predecessors: [B4] [B5]
+ Statements (0)
+ Next (StructuredExceptionHandling) Block[null]
+ }
+}
+Block[B7] - Exit
+ Predecessors: [B1] [B3]
+ Statements (0)
+";
+
+ VerifyFlowGraphAndDiagnosticsForTest(source, expectedFlowGraph, expectedDiagnostics);
+ }
+
+ [Fact]
+ public void UsingDeclaration_InsideForEmbeddedStatement()
+ {
+ var source = @"
+using System;
+using System.Collections;
+class C1 : IDisposable
+{
+ public void Dispose() { }
+}
+class C2
+{
+ public static void M()
+ /**/{
+ for (;;)
+ using C1 o1 = new C1();
+ }/**/
+}";
+
+ var expectedDiagnostics = new DiagnosticDescription[] {
+ // file.cs(13,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
+ // using C1 o1 = new C1();
+ Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "using C1 o1 = new C1();").WithLocation(13, 13)
+ };
+
+ var expectedFlowGraph = @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1}
+.locals {R1}
+{
+ Locals: [C1 o1]
+ Block[B1] - Block
+ Predecessors: [B0] [B6]
+ Statements (1)
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Left:
+ ILocalReferenceOperation: o1 (IsDeclaration: True) (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Right:
+ IObjectCreationOperation (Constructor: C1..ctor()) (OperationKind.ObjectCreation, Type: C1, IsInvalid) (Syntax: 'new C1()')
+ Arguments(0)
+ Initializer:
+ null
+ Next (Regular) Block[B2]
+ Entering: {R2} {R3}
+ .try {R2, R3}
+ {
+ Block[B2] - Block
+ Predecessors: [B1]
+ Statements (0)
+ Next (Regular) Block[B6]
+ Finalizing: {R4}
+ Leaving: {R3} {R2} {R1}
+ }
+ .finally {R4}
+ {
+ Block[B3] - Block
+ Predecessors (0)
+ Statements (0)
+ Jump if True (Regular) to Block[B5]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Next (Regular) Block[B4]
+ Block[B4] - Block
+ Predecessors: [B3]
+ Statements (1)
+ IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Instance Receiver:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
+ (ImplicitReference)
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Arguments(0)
+ Next (Regular) Block[B5]
+ Block[B5] - Block
+ Predecessors: [B3] [B4]
+ Statements (0)
+ Next (StructuredExceptionHandling) Block[null]
+ }
+}
+Block[B6] - Block
+ Predecessors: [B2]
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1}
+Block[B7] - Exit [UnReachable]
+ Predecessors (0)
+ Statements (0)
+";
+
+ VerifyFlowGraphAndDiagnosticsForTest(source, expectedFlowGraph, expectedDiagnostics);
+ }
+
+ [Fact]
+ public void UsingDeclaration_InsideForEachEmbeddedStatement()
+ {
+ var source = @"
+using System;
+using System.Collections;
+class C1 : IDisposable
+{
+ public void Dispose() { }
+}
+class C2
+{
+ public static void M(IEnumerable e)
+ /**/{
+ foreach (var o in e)
+ using C1 o1 = new C1();
+ }/**/
+}";
+
+ var expectedDiagnostics = new DiagnosticDescription[] {
+ // file.cs(13,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
+ // using C1 o1 = new C1();
+ Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "using C1 o1 = new C1();").WithLocation(13, 13)
+ };
+
+ var expectedFlowGraph = @"
+Block[B0] - Entry
+ Statements (0)
+ Next (Regular) Block[B1]
+ Entering: {R1}
+.locals {R1}
+{
+ CaptureIds: [0]
+ Block[B1] - Block
+ Predecessors: [B0]
+ Statements (1)
+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'e')
+ Value:
+ IInvocationOperation (virtual System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()) (OperationKind.Invocation, Type: System.Collections.IEnumerator, IsImplicit) (Syntax: 'e')
+ Instance Receiver:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Collections.IEnumerable, IsImplicit) (Syntax: 'e')
+ Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
+ (Identity)
+ Operand:
+ IParameterReferenceOperation: e (OperationKind.ParameterReference, Type: System.Collections.IEnumerable) (Syntax: 'e')
+ Arguments(0)
+ Next (Regular) Block[B2]
+ Entering: {R2} {R3}
+ .try {R2, R3}
+ {
+ Block[B2] - Block
+ Predecessors: [B1] [B5]
+ Statements (0)
+ Jump if False (Regular) to Block[B12]
+ IInvocationOperation (virtual System.Boolean System.Collections.IEnumerator.MoveNext()) (OperationKind.Invocation, Type: System.Boolean, IsImplicit) (Syntax: 'e')
+ Instance Receiver:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Collections.IEnumerator, IsImplicit) (Syntax: 'e')
+ Arguments(0)
+ Finalizing: {R9}
+ Leaving: {R3} {R2} {R1}
+ Next (Regular) Block[B3]
+ Entering: {R4}
+ .locals {R4}
+ {
+ Locals: [System.Object o]
+ Block[B3] - Block
+ Predecessors: [B2]
+ Statements (1)
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: null, IsImplicit) (Syntax: 'var')
+ Left:
+ ILocalReferenceOperation: o (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Object, IsImplicit) (Syntax: 'var')
+ Right:
+ IPropertyReferenceOperation: System.Object System.Collections.IEnumerator.Current { get; } (OperationKind.PropertyReference, Type: System.Object, IsImplicit) (Syntax: 'var')
+ Instance Receiver:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Collections.IEnumerator, IsImplicit) (Syntax: 'e')
+ Next (Regular) Block[B4]
+ Entering: {R5}
+ .locals {R5}
+ {
+ Locals: [C1 o1]
+ Block[B4] - Block
+ Predecessors: [B3]
+ Statements (1)
+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Left:
+ ILocalReferenceOperation: o1 (IsDeclaration: True) (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Right:
+ IObjectCreationOperation (Constructor: C1..ctor()) (OperationKind.ObjectCreation, Type: C1, IsInvalid) (Syntax: 'new C1()')
+ Arguments(0)
+ Initializer:
+ null
+ Next (Regular) Block[B5]
+ Entering: {R6} {R7}
+ .try {R6, R7}
+ {
+ Block[B5] - Block
+ Predecessors: [B4]
+ Statements (0)
+ Next (Regular) Block[B2]
+ Finalizing: {R8}
+ Leaving: {R7} {R6} {R5} {R4}
+ }
+ .finally {R8}
+ {
+ Block[B6] - Block
+ Predecessors (0)
+ Statements (0)
+ Jump if True (Regular) to Block[B8]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Next (Regular) Block[B7]
+ Block[B7] - Block
+ Predecessors: [B6]
+ Statements (1)
+ IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Instance Receiver:
+ IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
+ (ImplicitReference)
+ Operand:
+ ILocalReferenceOperation: o1 (OperationKind.LocalReference, Type: C1, IsInvalid, IsImplicit) (Syntax: 'o1 = new C1()')
+ Arguments(0)
+ Next (Regular) Block[B8]
+ Block[B8] - Block
+ Predecessors: [B6] [B7]
+ Statements (0)
+ Next (StructuredExceptionHandling) Block[null]
+ }
+ }
+ }
+ }
+ .finally {R9}
+ {
+ CaptureIds: [1]
+ Block[B9] - Block
+ Predecessors (0)
+ Statements (1)
+ IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'e')
+ Value:
+ IConversionOperation (TryCast: True, Unchecked) (OperationKind.Conversion, Type: System.IDisposable, IsImplicit) (Syntax: 'e')
+ Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
+ (ExplicitReference)
+ Operand:
+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Collections.IEnumerator, IsImplicit) (Syntax: 'e')
+ Jump if True (Regular) to Block[B11]
+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'e')
+ Operand:
+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.IDisposable, IsImplicit) (Syntax: 'e')
+ Next (Regular) Block[B10]
+ Block[B10] - Block
+ Predecessors: [B9]
+ Statements (1)
+ IInvocationOperation (virtual void System.IDisposable.Dispose()) (OperationKind.Invocation, Type: System.Void, IsImplicit) (Syntax: 'e')
+ Instance Receiver:
+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.IDisposable, IsImplicit) (Syntax: 'e')
+ Arguments(0)
+ Next (Regular) Block[B11]
+ Block[B11] - Block
+ Predecessors: [B9] [B10]
+ Statements (0)
+ Next (StructuredExceptionHandling) Block[null]
+ }
+}
+Block[B12] - Exit
+ Predecessors: [B2]
+ Statements (0)
+";
+
+ VerifyFlowGraphAndDiagnosticsForTest(source, expectedFlowGraph, expectedDiagnostics);
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/IOperation/Microsoft.CodeAnalysis.CSharp.IOperation.UnitTests.csproj b/src/Compilers/CSharp/Test/IOperation/Microsoft.CodeAnalysis.CSharp.IOperation.UnitTests.csproj
index fa56463514b76..125343cfda957 100644
--- a/src/Compilers/CSharp/Test/IOperation/Microsoft.CodeAnalysis.CSharp.IOperation.UnitTests.csproj
+++ b/src/Compilers/CSharp/Test/IOperation/Microsoft.CodeAnalysis.CSharp.IOperation.UnitTests.csproj
@@ -21,5 +21,5 @@
-
+
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Test/Semantic/Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj b/src/Compilers/CSharp/Test/Semantic/Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj
index e6be84fb87db4..0a1c989caf04b 100644
--- a/src/Compilers/CSharp/Test/Semantic/Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj
+++ b/src/Compilers/CSharp/Test/Semantic/Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj
@@ -22,5 +22,5 @@
-
+
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
index bd15620ed9f2e..e7dcc8b1a5108 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
@@ -13437,6 +13437,12 @@ class B : IA
}
";
var compilation = CreateCompilation(new[] { source }, options: WithNullableEnable());
+
+ var tree = compilation.SyntaxTrees[0];
+ var model = compilation.GetSemanticModel(tree);
+ var returnStatement = tree.GetRoot().DescendantNodes().OfType().Skip(1).Single();
+ AssertEx.Equal("S?[]", model.GetTypeInfo(returnStatement.Expression).Type.ToTestDisplayString());
+
compilation.VerifyDiagnostics(
// (17,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// S?[] IA.M2() where S : class
diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
index 8f462e286ab52..188a65c7fe99f 100644
--- a/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
@@ -2192,7 +2192,7 @@ protected override PortableExecutableReference WithPropertiesImpl(MetadataRefere
}
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoUsedAssembliesValidation), typeof(NoIOperationValidation), Reason = "IOperation skip: Compilation changes over time, adds new errors")]
public void MetadataConsistencyWhileEvolvingCompilation()
{
var md1 = AssemblyMetadata.CreateFromImage(CreateCompilation("public class C { }").EmitToArray());
diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs
index ff6b62174c9b0..18d41de5dea5c 100644
--- a/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Compilation/ReferenceManagerTests.cs
@@ -2525,7 +2525,7 @@ public class P
"mscorlib: global,Y,Y,Z");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution1()
{
// c - a -> b
@@ -2628,7 +2628,7 @@ public class C : A
"B, Version=3.0.0.0: Y,X");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_WeakIdentities1()
{
// c - a -> "b,v1,PKT=null"
@@ -2664,7 +2664,7 @@ public void MissingAssemblyResolution_WeakIdentities1()
"B, Version=1.0.0.0: ");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_WeakIdentities2()
{
// c - a -> "b,v1,PKT=null"
@@ -2717,7 +2717,7 @@ public void MissingAssemblyResolution_None()
resolver.VerifyResolutionAttempts();
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_ActualMissing()
{
// c - a -> d
@@ -2740,7 +2740,7 @@ public void MissingAssemblyResolution_ActualMissing()
///
/// Ignore assemblies returned by the resolver that don't match the reference identity.
///
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_MissingDueToResolutionMismatch()
{
// c - a -> b
@@ -2765,7 +2765,7 @@ public void MissingAssemblyResolution_MissingDueToResolutionMismatch()
"A -> B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_Multiple()
{
// c - a -> d
@@ -2790,7 +2790,7 @@ public void MissingAssemblyResolution_Multiple()
"B -> D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_Modules()
{
// c - a - d
@@ -2994,7 +2994,7 @@ public void MissingAssemblyResolution_BindingToExplicitReference_BetterVersion()
"E, Version=1.0.0.0");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_BindingToImplicitReference1()
{
// c - a -> d -> "b,v2"
@@ -3038,7 +3038,7 @@ public void MissingAssemblyResolution_BindingToImplicitReference1()
"B, Version=1.0.0.0: ");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_BindingToImplicitReference2()
{
// c - a -> d -> "b,v2"
@@ -3104,7 +3104,7 @@ public void MissingAssemblyResolution_BindingToImplicitReference2()
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_BindingToImplicitReference3()
{
// c - a -> d -> "b,v2"
@@ -3170,7 +3170,7 @@ public void MissingAssemblyResolution_BindingToImplicitReference3()
"A -> B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_Supersession_FxUnification()
{
var options = TestOptions.ReleaseDll.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);
@@ -3213,7 +3213,7 @@ public void MissingAssemblyResolution_Supersession_FxUnification()
"System, Version=2.0.0.0: ");
}
- [ConditionalFact(typeof(NoUsedAssembliesValidation))]
+ [ConditionalFact(typeof(NoIOperationValidation), typeof(NoUsedAssembliesValidation), Reason = "IOperation adds extra assemblies")]
public void MissingAssemblyResolution_Supersession_StrongNames()
{
var options = TestOptions.ReleaseDll.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);
diff --git a/src/Compilers/CSharp/Test/Symbol/Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj b/src/Compilers/CSharp/Test/Symbol/Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj
index 222edb6d31c18..b457b865a4d00 100644
--- a/src/Compilers/CSharp/Test/Symbol/Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj
+++ b/src/Compilers/CSharp/Test/Symbol/Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj
@@ -20,5 +20,5 @@
-
+
diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MethodImplementationFlagsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MethodImplementationFlagsTests.cs
new file mode 100644
index 0000000000000..2fde51c4104a6
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MethodImplementationFlagsTests.cs
@@ -0,0 +1,189 @@
+// Licensed to the .NET Foundation under one or more 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.Reflection;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols
+{
+ public class MethodImplementationFlagsTests : CSharpTestBase
+ {
+ [Fact]
+ public void TestInliningFlags()
+ {
+ var src = @"
+using System.Runtime.CompilerServices;
+
+public class C
+{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void M_Aggressive()
+ {
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public void M_NoInlining()
+ {
+ }
+}
+";
+
+ Action validator = module =>
+ {
+ var c = module.GlobalNamespace.GetMember("C");
+ var aggressiveInliningMethod = c.GetMember("M_Aggressive").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.AggressiveInlining, aggressiveInliningMethod.MethodImplementationFlags);
+
+ var noInliningMethod = c.GetMember("M_NoInlining").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.NoInlining, noInliningMethod.MethodImplementationFlags);
+ };
+
+ CompileAndVerify(src, sourceSymbolValidator: validator, symbolValidator: validator);
+ }
+
+
+ [Fact]
+ public void TestOptimizationFlags()
+ {
+ var src = @"
+using System.Runtime.CompilerServices;
+
+public class C
+{
+ [MethodImpl((MethodImplOptions)512)] // Aggressive optimization
+ public void M_Aggressive()
+ {
+ }
+
+ [MethodImpl(MethodImplOptions.NoOptimization)]
+ public void M_NoOptimization()
+ {
+ }
+}
+";
+ Action validator = module =>
+ {
+ var c = module.GlobalNamespace.GetMember("C");
+ var aggressiveOptimizationMethod = c.GetMember("M_Aggressive").GetPublicSymbol();
+#if !NET472 // MethodImplAttributes.AggressiveOptimization was introduced in .NET Core 3
+ Assert.Equal(MethodImplAttributes.AggressiveOptimization, aggressiveOptimizationMethod.MethodImplementationFlags);
+#else
+ Assert.Equal((MethodImplAttributes)512, aggressiveOptimizationMethod.MethodImplementationFlags);
+#endif
+
+ var noOptimizationMethod = c.GetMember("M_NoOptimization").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.NoOptimization, noOptimizationMethod.MethodImplementationFlags);
+ };
+
+ CompileAndVerify(src, sourceSymbolValidator: validator, symbolValidator: validator);
+ }
+
+ [Fact]
+ public void TestMixingOptimizationWithInliningFlags()
+ {
+ var src = @"
+using System.Runtime.CompilerServices;
+
+public class C
+{
+ [MethodImpl((MethodImplOptions)512 | MethodImplOptions.NoInlining)] // aggressive optimization and no inlining
+ public void M_AggressiveOpt_NoInlining()
+ {
+ }
+
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ public void M_NoOpt_NoInlining()
+ {
+ }
+
+ [MethodImpl((MethodImplOptions)512 | MethodImplOptions.AggressiveInlining)] // aggressive optimization and aggressive inlining
+ public void M_AggressiveOpt_AggressiveInlining()
+ {
+ }
+
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.AggressiveInlining)]
+ public void M_NoOpt_AggressiveInlining()
+ {
+ }
+}
+";
+
+ Action validator = module =>
+ {
+ var c = module.GlobalNamespace.GetMember("C");
+ var aggressiveOptNoInliningMethod = c.GetMember("M_AggressiveOpt_NoInlining").GetPublicSymbol();
+#if !NET472 // MethodImplAttributes.AggressiveOptimization was introduced in .NET Core 3
+ Assert.Equal(MethodImplAttributes.AggressiveOptimization | MethodImplAttributes.NoInlining, aggressiveOptNoInliningMethod.MethodImplementationFlags);
+#else
+ Assert.Equal((MethodImplAttributes)512 | MethodImplAttributes.NoInlining, aggressiveOptNoInliningMethod.MethodImplementationFlags);
+#endif
+
+ var noOptNoInliningMethod = c.GetMember("M_NoOpt_NoInlining").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.NoOptimization | MethodImplAttributes.NoInlining, noOptNoInliningMethod.MethodImplementationFlags);
+
+ var aggressiveOptAggressiveInliningMethod = c.GetMember("M_AggressiveOpt_AggressiveInlining").GetPublicSymbol();
+#if !NET472
+ Assert.Equal(MethodImplAttributes.AggressiveOptimization | MethodImplAttributes.AggressiveInlining, aggressiveOptAggressiveInliningMethod.MethodImplementationFlags);
+#else
+ Assert.Equal((MethodImplAttributes)512 | MethodImplAttributes.AggressiveInlining, aggressiveOptAggressiveInliningMethod.MethodImplementationFlags);
+#endif
+
+ var noOptAggressiveInliningMethod = c.GetMember("M_NoOpt_AggressiveInlining").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.NoOptimization | MethodImplAttributes.AggressiveInlining, noOptAggressiveInliningMethod.MethodImplementationFlags);
+ };
+
+ CompileAndVerify(src, sourceSymbolValidator: validator, symbolValidator: validator);
+ }
+
+ [Fact]
+ public void TestPreserveSigAndRuntimeFlags()
+ {
+ var src = @"
+using System.Runtime.CompilerServices;
+
+public class C
+{
+ [MethodImpl(MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)]
+ public void M()
+ {
+ }
+}
+";
+ Action validator = module =>
+ {
+ var c = module.GlobalNamespace.GetMember("C");
+ var method = c.GetMember("M").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.PreserveSig | MethodImplAttributes.Runtime, method.MethodImplementationFlags);
+ };
+
+ CompileAndVerify(src, sourceSymbolValidator: validator, symbolValidator: validator, verify: Verification.Skipped);
+ }
+
+ [Fact]
+ public void TestNativeFlag()
+ {
+ var src = @"
+using System.Runtime.CompilerServices;
+
+public class C
+{
+ [MethodImpl(MethodCodeType = MethodCodeType.Native)]
+ public extern void M();
+}
+";
+ Action validator = module =>
+ {
+ var c = module.GlobalNamespace.GetMember("C");
+ var method = c.GetMember("M").GetPublicSymbol();
+ Assert.Equal(MethodImplAttributes.Native, method.MethodImplementationFlags);
+ };
+
+ CompileAndVerify(src, sourceSymbolValidator: validator, symbolValidator: validator, verify: Verification.Skipped);
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Test/WinRT/Microsoft.CodeAnalysis.CSharp.WinRT.UnitTests.csproj b/src/Compilers/CSharp/Test/WinRT/Microsoft.CodeAnalysis.CSharp.WinRT.UnitTests.csproj
index d356fd48dad1f..72a86bd676d9a 100644
--- a/src/Compilers/CSharp/Test/WinRT/Microsoft.CodeAnalysis.CSharp.WinRT.UnitTests.csproj
+++ b/src/Compilers/CSharp/Test/WinRT/Microsoft.CodeAnalysis.CSharp.WinRT.UnitTests.csproj
@@ -18,5 +18,5 @@
-
+
diff --git a/src/Compilers/CSharp/csc/csc.csproj b/src/Compilers/CSharp/csc/csc.csproj
index 01e6741bb0961..cc6e6cabf8098 100644
--- a/src/Compilers/CSharp/csc/csc.csproj
+++ b/src/Compilers/CSharp/csc/csc.csproj
@@ -12,6 +12,7 @@
true
false
true
+ true
diff --git a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs
index cb2299046871d..025896ce62492 100644
--- a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs
+++ b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs
@@ -422,6 +422,22 @@ public static async Task AnyAsync(this ImmutableArray array, Func AnyAsync(this ImmutableArray array, Func> predicateAsync, TArg arg)
+ {
+ int n = array.Length;
+ for (int i = 0; i < n; i++)
+ {
+ var a = array[i];
+
+ if (await predicateAsync(a, arg).ConfigureAwait(false))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public static async ValueTask FirstOrDefaultAsync(this ImmutableArray array, Func> predicateAsync)
{
int n = array.Length;
diff --git a/src/Compilers/Core/Portable/Collections/StaticCast.cs b/src/Compilers/Core/Portable/Collections/StaticCast.cs
index c051c2972ef7b..9a869e8796138 100644
--- a/src/Compilers/Core/Portable/Collections/StaticCast.cs
+++ b/src/Compilers/Core/Portable/Collections/StaticCast.cs
@@ -10,10 +10,7 @@ internal static class StaticCast
{
internal static ImmutableArray From(ImmutableArray from) where TDerived : class, T
{
- // Remove the pragma when we get a version with https://github.com/dotnet/runtime/issues/39799 fixed
-#pragma warning disable CS8634
return ImmutableArray.CastUp(from);
-#pragma warning restore CS8634
}
}
}
diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs
index 0fbc3ee8b7b11..8f4c31390db47 100644
--- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs
+++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs
@@ -311,10 +311,16 @@ internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline basel
symbolMap = MapToMetadataSymbolMatcher;
}
+ var previousMethod = mappedMethod.PreviousMethod;
+ if (previousMethod is null)
+ {
+ previousMethod = (IMethodSymbolInternal)symbolMap.MapDefinitionOrNamespace(topLevelMethod);
+ }
+
return new EncVariableSlotAllocator(
symbolMap,
mappedMethod.SyntaxMap,
- mappedMethod.PreviousMethod,
+ previousMethod,
methodId,
previousLocals,
lambdaMap,
diff --git a/src/Compilers/Core/Portable/Emit/SemanticEdit.cs b/src/Compilers/Core/Portable/Emit/SemanticEdit.cs
index 6e94ee5e55467..caea2c3ce8e91 100644
--- a/src/Compilers/Core/Portable/Emit/SemanticEdit.cs
+++ b/src/Compilers/Core/Portable/Emit/SemanticEdit.cs
@@ -53,7 +53,7 @@ public struct SemanticEdit : IEquatable
///
/// The type of edit.
///
- /// The symbol from the earlier compilation, or null if the edit represents an addition.
+ /// The symbol from the earlier compilation, or null if the edit represents an addition or an update of the symbol from the previous compilation that exactly matches .
///
///
/// The symbol from the later compilation, or null if the edit represents a deletion.
@@ -74,7 +74,7 @@ public struct SemanticEdit : IEquatable
///
public SemanticEdit(SemanticEditKind kind, ISymbol? oldSymbol, ISymbol? newSymbol, Func? syntaxMap = null, bool preserveLocalVariables = false)
{
- if (oldSymbol == null && kind != SemanticEditKind.Insert)
+ if (oldSymbol == null && kind is not (SemanticEditKind.Insert or SemanticEditKind.Update))
{
throw new ArgumentNullException(nameof(oldSymbol));
}
diff --git a/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj b/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj
index ca5d78b8ad38b..df2f704340471 100644
--- a/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj
+++ b/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj
@@ -11,7 +11,6 @@
true
partial
true
- true
true
diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs
index 314a3491cf714..62885c64f7492 100644
--- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs
+++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs
@@ -3301,6 +3301,11 @@ void resetConditionalAccessTracker()
static bool isConditionalAccessInstancePresentInChildren(IOperation operation)
{
+ if (operation is InvalidOperation invalidOperation)
+ {
+ return checkInvalidChildren(invalidOperation);
+ }
+
// The conditional access should always be first leaf node in the subtree when performing a depth-first search. Visit the first child recursively
// until we either reach the bottom, or find the conditional access.
Operation currentOperation = (Operation)operation;
@@ -3310,12 +3315,31 @@ static bool isConditionalAccessInstancePresentInChildren(IOperation operation)
{
return true;
}
+ else if (enumerator.Current is InvalidOperation invalidChild)
+ {
+ return checkInvalidChildren(invalidChild);
+ }
currentOperation = (Operation)enumerator.Current;
}
return false;
}
+
+ static bool checkInvalidChildren(InvalidOperation operation)
+ {
+ // Invalid operations can have children ordering that doesn't put the conditional access instance first. For these cases,
+ // use a recursive check
+ foreach (var child in operation.ChildOperations)
+ {
+ if (child is IConditionalAccessInstanceOperation || isConditionalAccessInstancePresentInChildren(child))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
public override IOperation VisitConditionalAccessInstance(IConditionalAccessInstanceOperation operation, int? captureIdForResult)
diff --git a/src/Compilers/Core/Portable/Operations/OperationNodes.cs b/src/Compilers/Core/Portable/Operations/OperationNodes.cs
index 23a84af044677..dab2d1375d057 100644
--- a/src/Compilers/Core/Portable/Operations/OperationNodes.cs
+++ b/src/Compilers/Core/Portable/Operations/OperationNodes.cs
@@ -543,8 +543,9 @@ private BlockOperation(ImmutableArray statements, SemanticModel sema
// Intentionally skipping SetParentOperation: this is used by CreateTemporaryBlock for the purposes of the
// control flow factory, to temporarily create a new block for use in emulating the "block" a using variable
// declaration introduces. These statements already have a parent node, and `SetParentOperation`'s verification
- // would fail because that parent isn't this.
- Debug.Assert(statements.All(s => s.Parent != this && s.Parent!.Kind == OperationKind.Block));
+ // would fail because that parent isn't this. In error cases, the parent can also be a switch statement if
+ // the using declaration was used directly as an embedded statement in the case without a block.
+ Debug.Assert(statements.All(s => s.Parent != this && s.Parent!.Kind is OperationKind.Block or OperationKind.SwitchCase));
Operations = statements;
Locals = ImmutableArray.Empty;
}
diff --git a/src/Compilers/Core/Portable/PEWriter/CompilationOptionNames.cs b/src/Compilers/Core/Portable/PEWriter/CompilationOptionNames.cs
index fb4383b181cdf..5f12a18c7774b 100644
--- a/src/Compilers/Core/Portable/PEWriter/CompilationOptionNames.cs
+++ b/src/Compilers/Core/Portable/PEWriter/CompilationOptionNames.cs
@@ -28,7 +28,13 @@ internal static class CompilationOptionNames
public const string Unsafe = "unsafe";
public const string Nullable = "nullable";
public const string Define = "define";
- public const string Strict = "strict";
public const string SourceFileCount = "source-file-count";
+ public const string EmbedRuntime = "embed-runtime";
+ public const string GlobalNamespaces = "global-namespaces";
+ public const string RootNamespace = "root-namespace";
+ public const string OptionStrict = "option-strict";
+ public const string OptionInfer = "option-infer";
+ public const string OptionExplicit = "option-explicit";
+ public const string OptionCompareText = "option-compare-text";
}
}
diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
index 72b91127ec216..220f5b680ddfd 100644
--- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
@@ -15,6 +15,7 @@ Microsoft.CodeAnalysis.GeneratorPostInitializationContext.AddSource(string! hint
Microsoft.CodeAnalysis.GeneratorPostInitializationContext.AddSource(string! hintName, string! source) -> void
Microsoft.CodeAnalysis.GeneratorPostInitializationContext.CancellationToken.get -> System.Threading.CancellationToken
Microsoft.CodeAnalysis.GeneratorPostInitializationContext.GeneratorPostInitializationContext() -> void
+Microsoft.CodeAnalysis.IMethodSymbol.MethodImplementationFlags.get -> System.Reflection.MethodImplAttributes
Microsoft.CodeAnalysis.ITypeSymbol.IsRecord.get -> bool
Microsoft.CodeAnalysis.Operations.OperationWalker
Microsoft.CodeAnalysis.Operations.OperationWalker.OperationWalker() -> void
diff --git a/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs b/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
index 211b5102b2ea8..74b62ca605838 100644
--- a/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
+++ b/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
+using System.Reflection;
using System.Reflection.Metadata;
namespace Microsoft.CodeAnalysis
@@ -263,6 +264,11 @@ public interface IMethodSymbol : ISymbol
///
IMethodSymbol? PartialImplementationPart { get; }
+ ///
+ /// Returns the implementation flags for the given method symbol.
+ ///
+ MethodImplAttributes MethodImplementationFlags { get; }
+
///
/// Return true if this is a partial method definition without a body. If there
/// is an implementing body, it can be retrieved with .
diff --git a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs
index b6221f785c822..0c94c49ea6296 100644
--- a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs
+++ b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
#nullable disable
+// Uncomment to enable the IOperation test hook on all test runs. Do not commit this uncommented.
+//#define ROSLYN_TEST_IOPERATION
using System;
using System.Collections.Generic;
@@ -30,7 +32,13 @@ namespace Microsoft.CodeAnalysis.Test.Utilities
{
public static class CompilationExtensions
{
- internal static bool EnableVerifyIOperation { get; } = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ROSLYN_TEST_IOPERATION"));
+ internal static bool EnableVerifyIOperation { get; } =
+#if ROSLYN_TEST_IOPERATION
+ true;
+#else
+ !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ROSLYN_TEST_IOPERATION"));
+#endif
+
internal static bool EnableVerifyUsedAssemblies { get; } = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ROSLYN_TEST_USEDASSEMBLIES"));
internal static ImmutableArray EmitToArray(
diff --git a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs
index 813df800ed910..71d1f4be45a2d 100644
--- a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs
+++ b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs
@@ -823,7 +823,8 @@ void assertCaptureReferences(
((isFirstOperandOfDynamicOrUserDefinedLogicalOperator(reference) ||
isIncrementedNullableForToLoopControlVariable(reference) ||
isConditionalAccessReceiver(reference) ||
- isCoalesceAssignmentTarget(reference)) &&
+ isCoalesceAssignmentTarget(reference) ||
+ isObjectInitializerInitializedObjectTarget(reference)) &&
block.EnclosingRegion.EnclosingRegion.CaptureIds.Contains(id)),
$"Operation [{operationIndex}] in [{getBlockId(block)}] uses capture [{id.Value}] from another region. Should the regions be merged?", finalGraph);
}
@@ -875,6 +876,22 @@ bool isCoalesceAssignmentTarget(IFlowCaptureReferenceOperation reference)
conditionalAccess.Left == referenceSyntax;
}
+ bool isObjectInitializerInitializedObjectTarget(IFlowCaptureReferenceOperation reference)
+ {
+ if (reference.Language != LanguageNames.CSharp)
+ {
+ return false;
+ }
+
+ CSharpSyntaxNode referenceSyntax = applyParenthesizedOrNullSuppressionIfAnyCS((CSharpSyntaxNode)reference.Syntax);
+ return referenceSyntax.Parent is CSharp.Syntax.AssignmentExpressionSyntax
+ {
+ RawKind: (int)CSharp.SyntaxKind.SimpleAssignmentExpression,
+ Parent: InitializerExpressionSyntax { Parent: CSharp.Syntax.ObjectCreationExpressionSyntax },
+ Left: var left
+ } && left == referenceSyntax;
+ }
+
bool isFirstOperandOfDynamicOrUserDefinedLogicalOperator(IFlowCaptureReferenceOperation reference)
{
if (reference.Parent is IBinaryOperation binOp)
diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
index caccff3f41701..b4d0b13fe941d 100644
--- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
+++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
@@ -751,23 +751,32 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' LanguageVersion should already be mapped to an effective version at this point
Debug.Assert(LanguageVersion.MapSpecifiedToEffectiveVersion() = LanguageVersion)
WriteValue(builder, CompilationOptionNames.LanguageVersion, LanguageVersion.ToDisplayString())
+ WriteValue(builder, CompilationOptionNames.Checked, Options.CheckOverflow.ToString())
+ WriteValue(builder, CompilationOptionNames.OptionStrict, Options.OptionStrict.ToString())
+ WriteValue(builder, CompilationOptionNames.OptionInfer, Options.OptionInfer.ToString())
+ WriteValue(builder, CompilationOptionNames.OptionCompareText, Options.OptionCompareText.ToString())
+ WriteValue(builder, CompilationOptionNames.OptionExplicit, Options.OptionExplicit.ToString())
+ WriteValue(builder, CompilationOptionNames.EmbedRuntime, Options.EmbedVbCoreRuntime.ToString())
- If Options.CheckOverflow Then
- WriteValue(builder, CompilationOptionNames.Checked, Options.CheckOverflow.ToString())
+ If Options.GlobalImports.Length > 0 Then
+ WriteValue(builder, CompilationOptionNames.GlobalNamespaces, String.Join(";", Options.GlobalImports.Select(Function(x) x.Name)))
End If
- If Options.OptionStrict <> OptionStrict.Off Then
- WriteValue(builder, CompilationOptionNames.Strict, Options.OptionStrict.ToString())
+ If Not String.IsNullOrEmpty(Options.RootNamespace) Then
+ WriteValue(builder, CompilationOptionNames.RootNamespace, Options.RootNamespace)
End If
If Options.ParseOptions IsNot Nothing Then
- Dim preprocessorStrings = Options.ParseOptions.PreprocessorSymbols.Select(Function(p)
- If (p.Value Is Nothing) Then
- Return p.Key
- End If
-
- Return p.Key + "=" + p.Value.ToString()
- End Function)
+ Dim preprocessorStrings = Options.ParseOptions.PreprocessorSymbols.Select(
+ Function(p) As String
+ If TypeOf p.Value Is String Then
+ Return p.Key + "=""" + p.Value.ToString() + """"
+ ElseIf p.Value Is Nothing Then
+ Return p.Key
+ Else
+ Return p.Key + "=" + p.Value.ToString()
+ End If
+ End Function)
WriteValue(builder, CompilationOptionNames.Define, String.Join(",", preprocessorStrings))
End If
End Sub
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
index 671df214c5b0d..29a305bf7c492 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
@@ -895,6 +895,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
+ Private ReadOnly Property IMethodSymbol_MethodImplementationFlags As System.Reflection.MethodImplAttributes Implements IMethodSymbol.MethodImplementationFlags
+ Get
+ Return Me.ImplementationAttributes
+ End Get
+ End Property
+
Private ReadOnly Property IMethodSymbol_IsExtensionMethod As Boolean Implements IMethodSymbol.IsExtensionMethod
Get
Return Me.IsExtensionMethod
diff --git a/src/Compilers/VisualBasic/Test/Emit/Microsoft.CodeAnalysis.VisualBasic.Emit.UnitTests.vbproj b/src/Compilers/VisualBasic/Test/Emit/Microsoft.CodeAnalysis.VisualBasic.Emit.UnitTests.vbproj
index f31c1eeb62e5a..991366659f83d 100644
--- a/src/Compilers/VisualBasic/Test/Emit/Microsoft.CodeAnalysis.VisualBasic.Emit.UnitTests.vbproj
+++ b/src/Compilers/VisualBasic/Test/Emit/Microsoft.CodeAnalysis.VisualBasic.Emit.UnitTests.vbproj
@@ -168,5 +168,5 @@
-
+
diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/VisualBasicDeterministicBuildCompilationTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/VisualBasicDeterministicBuildCompilationTests.vb
index 1223780ba8c0a..12a856433127e 100644
--- a/src/Compilers/VisualBasic/Test/Emit/PDB/VisualBasicDeterministicBuildCompilationTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/PDB/VisualBasicDeterministicBuildCompilationTests.vb
@@ -33,7 +33,7 @@ Public Class VisualBasicDeterministicBuildCompilationTests
"define",
originalOptions.ParseOptions.PreprocessorSymbols,
isDefault:=Function(v) v.IsEmpty,
- toString:=Function(v) String.Join(",", v.Select(Function(p) If(p.Value IsNot Nothing, $"{p.Key}={p.Value}", p.Key))))
+ toString:=Function(v) String.Join(",", v.Select(Function(p) If(p.Value IsNot Nothing, $"{p.Key}=""{p.Value}""", p.Key))))
End Sub
Private Sub TestDeterministicCompilationVB(syntaxTrees As SyntaxTree(), compilationOptions As VisualBasicCompilationOptions, emitOptions As EmitOptions, ParamArray metadataReferences() As TestMetadataReferenceInfo)
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Microsoft.CodeAnalysis.VisualBasic.Semantic.UnitTests.vbproj b/src/Compilers/VisualBasic/Test/Semantic/Microsoft.CodeAnalysis.VisualBasic.Semantic.UnitTests.vbproj
index 0fed500079196..57ff244223cac 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Microsoft.CodeAnalysis.VisualBasic.Semantic.UnitTests.vbproj
+++ b/src/Compilers/VisualBasic/Test/Semantic/Microsoft.CodeAnalysis.VisualBasic.Semantic.UnitTests.vbproj
@@ -83,5 +83,5 @@
-
+
\ No newline at end of file
diff --git a/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj b/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj
index 84e8efbcdfad3..e08abf620eb6f 100644
--- a/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj
+++ b/src/Compilers/VisualBasic/Test/Symbol/Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj
@@ -32,5 +32,5 @@
-
+
\ No newline at end of file
diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/MethodImplementationFlagsTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/MethodImplementationFlagsTests.vb
new file mode 100644
index 0000000000000..4ff0d5b4862f8
--- /dev/null
+++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/MethodImplementationFlagsTests.vb
@@ -0,0 +1,164 @@
+' Licensed to the .NET Foundation under one or more agreements.
+' The .NET Foundation licenses this file to you under the MIT license.
+' See the LICENSE file in the project root for more information.
+
+Imports System.Reflection
+Imports Microsoft.CodeAnalysis.Test.Utilities
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
+
+Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols
+
+ Public Class MethodImplementationFlagsTests
+ Inherits BasicTestBase
+
+
+ Public Sub TestInliningFlags()
+ Dim src =
+
+
+ Public Sub M_Aggressive()
+ End Sub
+
+
+ Public Sub M_NoInlining()
+ End Sub
+End Class
+ ]]>
+
+
+ Dim validator As Action(Of ModuleSymbol) = Sub([module])
+ Dim c = [module].GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
+ Dim aggressiveInliningMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_Aggressive")
+ Assert.Equal(MethodImplAttributes.AggressiveInlining, aggressiveInliningMethod.MethodImplementationFlags)
+ Dim noInliningMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_NoInlining")
+ Assert.Equal(MethodImplAttributes.NoInlining, noInliningMethod.MethodImplementationFlags)
+ End Sub
+
+ CompileAndVerify(src, sourceSymbolValidator:=validator, symbolValidator:=validator, useLatestFramework:=True)
+ End Sub
+
+
+ Public Sub TestOptimizationFlags()
+ Dim src =
+
+ ' Aggressive optimization
+ Public Sub M_Aggressive()
+ End Sub
+
+
+ Public Sub M_NoOptimization()
+ End Sub
+End Class
+ ]]>
+
+
+ Dim validator As Action(Of ModuleSymbol) = Sub([module])
+ Dim c = [module].GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
+ Dim aggressiveOptimizationMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_Aggressive")
+ Assert.Equal(CType(512, MethodImplAttributes), aggressiveOptimizationMethod.MethodImplementationFlags)
+ Dim noOptimizationMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_NoOptimization")
+ Assert.Equal(MethodImplAttributes.NoOptimization, noOptimizationMethod.MethodImplementationFlags)
+ End Sub
+
+ CompileAndVerify(src, sourceSymbolValidator:=validator, symbolValidator:=validator)
+ End Sub
+
+
+ Public Sub TestMixingOptimizationWithInliningFlags()
+ Dim src =
+
+ ' aggressive optimization and no inlining
+ Public Sub M_AggressiveOpt_NoInlining()
+ End Sub
+
+
+ Public Sub M_NoOpt_NoInlining()
+ End Sub
+
+ ' aggressive optimization and aggressive inlining
+ Public Sub M_AggressiveOpt_AggressiveInlining()
+ End Sub
+
+
+ Public Sub M_NoOpt_AggressiveInlining()
+ End Sub
+End Class
+ ]]>
+
+
+ Dim validator As Action(Of ModuleSymbol) = Sub([module])
+ Dim c = [module].GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
+ Dim aggressiveOptNoInliningMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_AggressiveOpt_NoInlining")
+ Assert.Equal(CType(512, MethodImplAttributes) Or MethodImplAttributes.NoInlining, aggressiveOptNoInliningMethod.MethodImplementationFlags)
+ Dim noOptNoInliningMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_NoOpt_NoInlining")
+ Assert.Equal(MethodImplAttributes.NoOptimization Or MethodImplAttributes.NoInlining, noOptNoInliningMethod.MethodImplementationFlags)
+ Dim aggressiveOptAggressiveInliningMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_AggressiveOpt_AggressiveInlining")
+ Assert.Equal(CType(512, MethodImplAttributes) Or MethodImplAttributes.AggressiveInlining, aggressiveOptAggressiveInliningMethod.MethodImplementationFlags)
+ Dim noOptAggressiveInliningMethod As IMethodSymbol = c.GetMember(Of MethodSymbol)("M_NoOpt_AggressiveInlining")
+ Assert.Equal(MethodImplAttributes.NoOptimization Or MethodImplAttributes.AggressiveInlining, noOptAggressiveInliningMethod.MethodImplementationFlags)
+ End Sub
+
+ CompileAndVerify(src, sourceSymbolValidator:=validator, symbolValidator:=validator, useLatestFramework:=True)
+ End Sub
+
+
+ Public Sub TestPreserveSigAndRuntimeFlags()
+ Dim src =
+
+
+ Public Sub M()
+ End Sub
+End Class
+ ]]>
+
+
+ Dim validator As Action(Of ModuleSymbol) = Sub([module])
+ Dim c = [module].GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
+ Dim method As IMethodSymbol = c.GetMember(Of MethodSymbol)("M")
+ Assert.Equal(MethodImplAttributes.PreserveSig Or MethodImplAttributes.Runtime, method.MethodImplementationFlags)
+ End Sub
+
+ CompileAndVerify(src, sourceSymbolValidator:=validator, symbolValidator:=validator, verify:=Verification.Skipped)
+ End Sub
+
+
+ Public Sub TestNativeFlag()
+ Dim src =
+
+
+ Public Sub M()
+ End Sub
+End Class
+ ]]>
+
+
+ Dim validator As Action(Of ModuleSymbol) = Sub([module])
+ Dim c = [module].GlobalNamespace.GetMember(Of NamedTypeSymbol)("C")
+ Dim method As IMethodSymbol = c.GetMember(Of MethodSymbol)("M")
+ Assert.Equal(MethodImplAttributes.Native, method.MethodImplementationFlags)
+ End Sub
+
+ CompileAndVerify(src, sourceSymbolValidator:=validator, symbolValidator:=validator, verify:=Verification.Skipped)
+ End Sub
+ End Class
+End Namespace
diff --git a/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs b/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs
index a778d6e06ad74..da94baee92d68 100644
--- a/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs
+++ b/src/Dependencies/Collections/Internal/SegmentedArrayHelper.cs
@@ -4,6 +4,8 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
namespace Microsoft.CodeAnalysis.Collections.Internal
{
@@ -14,6 +16,52 @@ internal static class SegmentedArrayHelper
// Large value types may benefit from a smaller number.
internal const int IntrosortSizeThreshold = 16;
+ ///
+ /// A combination of and
+ /// .
+ ///
+ [SuppressMessage("Documentation", "CA1200:Avoid using cref tags with a prefix", Justification = "The field is not supported in all compilation targets.")]
+ internal const MethodImplOptions FastPathMethodImplOptions = MethodImplOptions.AggressiveInlining | (MethodImplOptions)512;
+
+ [MethodImpl(FastPathMethodImplOptions)]
+ internal static int GetSegmentSize()
+ {
+ if (Unsafe.SizeOf() == Unsafe.SizeOf
/// The number of elements in each page of the segmented array. Must be a power of 2.
/// The shift to apply to the absolute index to get the page index within a segmented array.
- internal static int CalculateSegmentShift(int segmentSize)
+ private static int CalculateSegmentShift(int segmentSize)
{
var segmentShift = 0;
while (0 != (segmentSize >>= 1))
@@ -67,10 +115,36 @@ internal static int CalculateSegmentShift(int segmentSize)
///
/// The number of elements in each page of the segmented array. Must be a power of 2.
/// The bit mask to obtain the index within a page from an absolute index within a segmented array.
- internal static int CalculateOffsetMask(int segmentSize)
+ private static int CalculateOffsetMask(int segmentSize)
{
Debug.Assert(segmentSize == 1 || (segmentSize & (segmentSize - 1)) == 0, "Expected size of 1, or a power of 2");
return segmentSize - 1;
}
+
+ internal static class TestAccessor
+ {
+ public static int CalculateSegmentSize(int elementSize)
+ => SegmentedArrayHelper.CalculateSegmentSize(elementSize);
+
+ public static int CalculateSegmentShift(int elementSize)
+ => SegmentedArrayHelper.CalculateSegmentShift(elementSize);
+
+ public static int CalculateOffsetMask(int elementSize)
+ => SegmentedArrayHelper.CalculateOffsetMask(elementSize);
+ }
+
+ private static class ReferenceTypeSegmentHelper
+ {
+ public static readonly int SegmentSize = CalculateSegmentSize(Unsafe.SizeOf());
+ public static readonly int SegmentShift = CalculateSegmentShift(SegmentSize);
+ public static readonly int OffsetMask = CalculateOffsetMask(SegmentSize);
+ }
+
+ private static class ValueTypeSegmentHelper
+ {
+ public static readonly int SegmentSize = CalculateSegmentSize(Unsafe.SizeOf());
+ public static readonly int SegmentShift = CalculateSegmentShift(SegmentSize);
+ public static readonly int OffsetMask = CalculateOffsetMask(SegmentSize);
+ }
}
}
diff --git a/src/Dependencies/Collections/SegmentedArray`1.cs b/src/Dependencies/Collections/SegmentedArray`1.cs
index 970aba7cdfcec..ed6e06652d2d2 100644
--- a/src/Dependencies/Collections/SegmentedArray`1.cs
+++ b/src/Dependencies/Collections/SegmentedArray`1.cs
@@ -30,17 +30,38 @@ namespace Microsoft.CodeAnalysis.Collections
/// including any padding the implementation chooses to add. Specifically, array elements lie sizeof
/// bytes apart.
///
- private static readonly int s_segmentSize = SegmentedArrayHelper.CalculateSegmentSize(Unsafe.SizeOf());
+ private static int SegmentSize
+ {
+ [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)]
+ get
+ {
+ return SegmentedArrayHelper.GetSegmentSize();
+ }
+ }
///
/// The bit shift to apply to an array index to get the page index within .
///
- private static readonly int s_segmentShift = SegmentedArrayHelper.CalculateSegmentShift(s_segmentSize);
+ private static int SegmentShift
+ {
+ [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)]
+ get
+ {
+ return SegmentedArrayHelper.GetSegmentShift();
+ }
+ }
///
/// The bit mask to apply to an array index to get the index within a page of .
///
- private static readonly int s_offsetMask = SegmentedArrayHelper.CalculateOffsetMask(s_segmentSize);
+ private static int OffsetMask
+ {
+ [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)]
+ get
+ {
+ return SegmentedArrayHelper.GetOffsetMask();
+ }
+ }
private readonly int _length;
private readonly T[][] _items;
@@ -59,17 +80,17 @@ public SegmentedArray(int length)
}
else
{
- _items = new T[(length + s_segmentSize - 1) >> s_segmentShift][];
+ _items = new T[(length + SegmentSize - 1) >> SegmentShift][];
for (var i = 0; i < _items.Length - 1; i++)
{
- _items[i] = new T[s_segmentSize];
+ _items[i] = new T[SegmentSize];
}
// Make sure the last page only contains the number of elements required for the desired length. This
// collection is not resizeable so any additional padding would be a waste of space.
//
// Avoid using (length & s_offsetMask) because it doesn't handle a last page size of s_segmentSize.
- var lastPageSize = length - ((_items.Length - 1) << s_segmentShift);
+ var lastPageSize = length - ((_items.Length - 1) << SegmentShift);
_items[_items.Length - 1] = new T[lastPageSize];
_length = length;
@@ -94,9 +115,10 @@ private SegmentedArray(int length, T[][] items)
public ref T this[int index]
{
+ [MethodImpl(SegmentedArrayHelper.FastPathMethodImplOptions)]
get
{
- return ref _items[index >> s_segmentShift][index & s_offsetMask];
+ return ref _items[index >> SegmentShift][index & OffsetMask];
}
}
@@ -135,7 +157,7 @@ public void CopyTo(Array array, int index)
{
for (var i = 0; i < _items.Length; i++)
{
- _items[i].CopyTo(array, index + (i * s_segmentSize));
+ _items[i].CopyTo(array, index + (i * SegmentSize));
}
}
@@ -144,7 +166,7 @@ void ICollection.CopyTo(T[] array, int arrayIndex)
for (var i = 0; i < _items.Length; i++)
{
ICollection collection = _items[i];
- collection.CopyTo(array, arrayIndex + (i * s_segmentSize));
+ collection.CopyTo(array, arrayIndex + (i * SegmentSize));
}
}
@@ -207,7 +229,7 @@ int IList.IndexOf(object? value)
var index = list.IndexOf(value);
if (index >= 0)
{
- return index + i * s_segmentSize;
+ return index + i * SegmentSize;
}
}
@@ -222,7 +244,7 @@ int IList.IndexOf(T value)
var index = list.IndexOf(value);
if (index >= 0)
{
- return index + i * s_segmentSize;
+ return index + i * SegmentSize;
}
}
@@ -393,7 +415,7 @@ public TestAccessor(SegmentedArray array)
_array = array;
}
- public static int SegmentSize => s_segmentSize;
+ public static int SegmentSize => SegmentedArray.SegmentSize;
public T[][] Items => _array._items;
}
diff --git a/src/EditorFeatures/CSharp.Wpf/CSharpEditorWpfResources.cs b/src/EditorFeatures/CSharp.Wpf/CSharpEditorWpfResources.cs
deleted file mode 100644
index 30edc5256e4af..0000000000000
--- a/src/EditorFeatures/CSharp.Wpf/CSharpEditorWpfResources.cs
+++ /dev/null
@@ -1,15 +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
-
-namespace Microsoft.CodeAnalysis.Editor.CSharp
-{
- ///
- /// Stub type - replace with type generated from resx file when resources are needed in this assembly.
- ///
- internal static class CSharpEditorWpfResources
- {
- }
-}
diff --git a/src/EditorFeatures/CSharp.Wpf/Microsoft.CodeAnalysis.CSharp.EditorFeatures.Wpf.csproj b/src/EditorFeatures/CSharp.Wpf/Microsoft.CodeAnalysis.CSharp.EditorFeatures.Wpf.csproj
deleted file mode 100644
index a4754d0868f7f..0000000000000
--- a/src/EditorFeatures/CSharp.Wpf/Microsoft.CodeAnalysis.CSharp.EditorFeatures.Wpf.csproj
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
- Library
- Microsoft.CodeAnalysis.Editor.CSharp
- net472
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharp.Wpf/PublicAPI.Shipped.txt b/src/EditorFeatures/CSharp.Wpf/PublicAPI.Shipped.txt
deleted file mode 100644
index e69de29bb2d1d..0000000000000
diff --git a/src/EditorFeatures/CSharp.Wpf/PublicAPI.Unshipped.txt b/src/EditorFeatures/CSharp.Wpf/PublicAPI.Unshipped.txt
deleted file mode 100644
index 8b137891791fe..0000000000000
--- a/src/EditorFeatures/CSharp.Wpf/PublicAPI.Unshipped.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs
index 3e374089a2f69..711a0f99440e6 100644
--- a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs
+++ b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler_Helpers.cs
@@ -748,6 +748,7 @@ private static bool ShouldRemoveBraceForObjectCreationExpression(ObjectCreationE
// event EventHandler Bar {add; remove;}
private static bool ShouldRemoveBraceForAccessorDeclaration(AccessorDeclarationSyntax accessorDeclarationNode, int caretPosition)
=> accessorDeclarationNode.Body != null
+ && accessorDeclarationNode.Body.Statements.IsEmpty()
&& accessorDeclarationNode.ExpressionBody == null
&& accessorDeclarationNode.Parent != null
&& accessorDeclarationNode.Parent.IsParentKind(SyntaxKind.PropertyDeclaration)
diff --git a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs
index e867208baf073..b051ac686ddfe 100644
--- a/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs
+++ b/src/EditorFeatures/CSharpTest/AutomaticCompletion/AutomaticLineEnderTests.cs
@@ -1258,6 +1258,74 @@ public int this[int i]
}");
}
+ [WpfFact]
+ public void TestNonEmptyGetAccessor()
+ {
+ Test(@"
+public Class Bar
+{
+ public int P
+ {
+ get
+ {
+ if (true)
+ $$
+ {
+ return 1;
+ }
+ }
+ }
+}",
+ @"
+public Class Bar
+{
+ public int P
+ {
+ get
+ {
+ i$$f ($$true$$)$$
+ {
+ return 1;
+ }
+ }
+ }
+}");
+ }
+
+ [WpfFact]
+ public void TestNonEmptySetAccessor()
+ {
+ Test(@"
+public Class Bar
+{
+ public int P
+ {
+ get;
+ set
+ {
+ if (true)
+ $$
+ {
+ }
+ }
+ }
+}",
+ @"
+public Class Bar
+{
+ public int P
+ {
+ get;
+ set
+ {
+ i$$f (t$$rue)$$
+ {
+ }
+ }
+ }
+}");
+ }
+
[WpfFact]
public void TestSetAccessorOfIndexer()
{
@@ -1470,6 +1538,27 @@ public class Bar
}");
}
+ [WpfFact]
+ public void TestNonEmptyProperty()
+ {
+ Test(@"
+public class Bar
+{
+ public int Foo
+ {
+ get { }
+ $$
+ }
+}", @"
+public class Bar
+{
+ public int Foo
+ {
+ $$get$$ { }$$
+ }
+}");
+ }
+
[WpfFact]
public void TestMulitpleFields()
{
@@ -1531,6 +1620,29 @@ public class Bar
Test(secondResult, firstResult);
}
+ [WpfFact]
+ public void TestNonEmptyEvent()
+ {
+ Test(@"
+using System;
+public class Bar
+{
+ public event EventHandler Foo
+ {
+ add { }
+ $$
+ }
+}", @"
+using System;
+public class Bar
+{
+ public event EventHandler Foo
+ {
+ $$add$$ {$$ }$$
+ }
+}");
+ }
+
[WpfFact]
public void TestObjectCreationExpressionWithParenthesis()
{
@@ -1808,6 +1920,40 @@ public class Foo
Test(secondResult, firstResult);
}
+ [WpfFact]
+ public void TestObjectCreationExpressionWithNonEmptyInitializer()
+ {
+ Test(
+ @"
+public class Bar
+{
+ public void M()
+ {
+ var a = new Foo() { HH = 1, PP = 2 };
+ $$
+ }
+}
+public class Foo
+{
+ public int HH { get; set; }
+ public int PP { get; set; }
+}",
+ @"
+public class Bar
+{
+ public void M()
+ {
+ var a = n$$ew Fo$$o($$) {$$ HH = 1$$, PP = 2 $$};
+ }
+}
+public class Foo
+{
+ public int HH { get; set; }
+ public int PP { get; set; }
+}");
+
+ }
+
[WpfFact]
public void TestIfStatementWithInnerStatement()
{
diff --git a/src/EditorFeatures/CSharpTest/CommentSelection/CSharpToggleLineCommentCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/CommentSelection/CSharpToggleLineCommentCommandHandlerTests.cs
index 33058b624083b..8aeecd61b933c 100644
--- a/src/EditorFeatures/CSharpTest/CommentSelection/CSharpToggleLineCommentCommandHandlerTests.cs
+++ b/src/EditorFeatures/CSharpTest/CommentSelection/CSharpToggleLineCommentCommandHandlerTests.cs
@@ -56,7 +56,7 @@ class C
{
void M()
{
-[| //var i = 1;|]
+ //var[||] i = 1;
}
}";
@@ -81,7 +81,7 @@ class C
{
void M()
{
-[| //var i = 1;|]
+[||] //var i = 1;
}
}";
@@ -106,7 +106,7 @@ class C
{
void M()
{
-[| //var i = 1;|]
+ [|//var i = 1;|]
}
}";
@@ -131,7 +131,7 @@ class C
{
void M()
{
-[| //var i = 1;|]
+ //var [|i = 1;|]
}
}";
@@ -185,7 +185,7 @@ class C
{
void M()
{
-[| //var i = 1; // A comment.|]
+ //var i = 1; // A [|comment|].
}
}";
@@ -210,7 +210,7 @@ class C
{
void M()
{
-[| //var i = 1; // A comment.|]
+ //var i = 1; [|// A comment.|]
}
}";
@@ -235,7 +235,7 @@ class C
{
void M()
{
-[| //var i = 1; // A comment.|]
+ [|//var i = 1; // A comment.|]
}
}";
@@ -260,7 +260,7 @@ class C
{
void M()
{
-[| //var i = 1; // A comment.|]
+ //var [||]i = 1; // A comment.
}
}";
@@ -285,7 +285,7 @@ class C
{
void M()
{
-[| //var i = 1; // A comment.|]
+ //var i = 1; // A [||]comment.
}
}";
@@ -310,7 +310,7 @@ class C
{
void M()
{
-[| //string s = '\\';|]
+ [|//string s = '\\';|]
}
}";
@@ -336,7 +336,7 @@ class C
{
void M()
{
-[| //var i = 1;
+ [|//var i = 1;
//var j = 2;|]
}
}";
@@ -396,7 +396,7 @@ class C
{
void M()
{
-[| ////var i = 1;
+ [|////var i = 1;
//var j = 2;|]
}
}";
@@ -423,7 +423,7 @@ class C
{
void M()
{
-[| //var i = 1; // A comment.
+ [|//var i = 1; // A comment.
//var j = 2;|]
}
}";
@@ -479,8 +479,8 @@ class C
{
void M()
{
-[| //var i = 1;|]
-[| //var j = 2;|]
+ //var [||]i = 1;
+ //var [||]j = 2;
}
}";
@@ -506,8 +506,8 @@ class C
{
void M()
{
-[| //var i = 1;|]
-[| //var j = 2;|]
+ [|//var i = 1;|]
+ [|//var j = 2;|]
}
}";
@@ -523,7 +523,7 @@ class C
{
void M()
{
- [|//var i = 1;|]
+ [|//var i = |]1;
[|var j = 2;|]
}
}";
@@ -533,8 +533,8 @@ class C
{
void M()
{
-[| ////var i = 1;|]
-[| //var j = 2;|]
+ [|////var i = |]1;
+ [|//var j = 2;|]
}
}";
@@ -559,7 +559,7 @@ void M()
{
void M()
{
-[| //var i = 1;|]
+ [|//var i = 1;|]
}
}";
@@ -584,7 +584,7 @@ class C
{
void M()
{
-[| var i = 1;|]
+ var[||] i = 1;
}
}";
@@ -609,7 +609,7 @@ class C
{
void M()
{
-[| var i = 1;|]
+ [||] var i = 1;
}
}";
@@ -634,7 +634,7 @@ class C
{
void M()
{
-[| var i = 1; // A comment.|]
+ var i = 1; // A [||]comment.
}
}";
@@ -659,7 +659,7 @@ class C
{
void M()
{
-[| //var i = 1;|]
+ //var[||] i = 1;
}
}";
@@ -684,7 +684,7 @@ class C
{
void M()
{
-[| var i = 1;|]
+ [|var i = 1;|]
}
}";
@@ -709,7 +709,7 @@ class C
{
void M()
{
-[| var i = 1;|]
+ var [|i = 1;|]
}
}";
@@ -763,7 +763,7 @@ class C
{
void M()
{
-[| string s = '\\';|]
+ [|string s = '\\';|]
}
}";
@@ -789,7 +789,7 @@ class C
{
void M()
{
-[| var i = 1;
+ [|var i = 1;
var j = 2;|]
}
}";
@@ -849,7 +849,7 @@ class C
{
void M()
{
-[| var i = 1; // A comment.
+ [|var i = 1; // A comment.
var j = 2;|]
}
}";
@@ -906,9 +906,9 @@ class C
{
void M()
{
-[| var i = 1;|]
+ var [||]i = 1;
[||]
-[| var j = 2;|]
+ var [||]j = 2;
}
}";
@@ -935,9 +935,9 @@ class C
{
void M()
{
-[| var i = 1;|]
+ [|var i = 1;|]
[||]
-[| var j = 2;|]
+ [|var j = 2;|]
}
}";
@@ -962,7 +962,7 @@ void M()
{
void M()
{
-[| var i = 1;|]
+ [|var i = 1;|]
}
}";
@@ -990,7 +990,7 @@ class C
{
void M()
{
-[| ////var i = 1;
+ [|////var i = 1;
//var j = 2;|]
}
@@ -1000,7 +1000,7 @@ class C
{
void M()
{
-[| //var i = 1;
+ [|//var i = 1;
var j = 2;|]
}
@@ -1019,7 +1019,7 @@ class C
{
void M()
{
- [|//var i = 1;|]
+ [|//var i = |]1;
[||]
[|var j = 2;|]
}
@@ -1031,9 +1031,9 @@ class C
{
void M()
{
-[| ////var i = 1;|]
+ [|////var i = |]1;
[||]
-[| //var j = 2;|]
+ [|//var j = 2;|]
}
}",
@"
@@ -1041,9 +1041,9 @@ class C
{
void M()
{
-[| //var i = 1;|]
+ [|//var i = |]1;
[||]
-[| var j = 2;|]
+ [|var j = 2;|]
}
}"
};
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
index cfb3d808f9c38..3ca7347fd4759 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
@@ -34,13 +34,16 @@ public class ExtensionMethodImportCompletionProviderTests : AbstractCSharpComple
private bool HideAdvancedMembers { get; set; }
+ private bool UsePartialSemantic { get; set; } = false;
+
protected override OptionSet WithChangedOptions(OptionSet options)
{
return options
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, ShowImportCompletionItemsOptionValue)
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion)
.WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers)
- .WithChangedOption(CompletionServiceOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion, TimeoutInMilliseconds);
+ .WithChangedOption(CompletionServiceOptions.TimeoutInMillisecondsForExtensionMethodImportCompletion, TimeoutInMilliseconds)
+ .WithChangedOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion, UsePartialSemantic);
}
protected override TestComposition GetComposition()
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs
index 808c679e06f5c..61cf9343de22a 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TypeImportCompletionProviderTests.cs
@@ -33,13 +33,16 @@ internal override Type GetCompletionProviderType()
private bool HideAdvancedMembers { get; set; }
+ private bool UsePartialSemantic { get; set; } = false;
+
protected override OptionSet WithChangedOptions(OptionSet options)
{
return options
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, ShowImportCompletionItemsOptionValue)
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion)
.WithChangedOption(CompletionServiceOptions.DisallowAddingImports, DisallowAddingImports)
- .WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers);
+ .WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers)
+ .WithChangedOption(CompletionServiceOptions.UsePartialSemanticForImportCompletion, UsePartialSemantic);
}
protected override TestComposition GetComposition()
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
index 035215aa090ab..7b579419d8e81 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
@@ -458,9 +458,11 @@ int Test()
}";
var expected =
-@"class Program
+@"using System.Threading.Tasks;
+
+class Program
{
- async System.Threading.Tasks.Task TestAsync()
+ async Task TestAsync()
{
await Task.Delay(1);
}
@@ -481,9 +483,11 @@ Program Test()
}";
var expected =
-@"class Program
+@"using System.Threading.Tasks;
+
+class Program
{
- async System.Threading.Tasks.Task TestAsync()
+ async Task TestAsync()
{
await Task.Delay(1);
}
@@ -1199,9 +1203,11 @@ void M()
}
}
}",
-@"class C
+@"using System.Threading.Tasks;
+
+class C
{
- async System.Threading.Tasks.Task MAsync()
+ async Task MAsync()
{
await using (var x = new object())
{
@@ -1238,9 +1244,11 @@ void M()
}
}
}",
-@"class C
+@"using System.Threading.Tasks;
+
+class C
{
- async System.Threading.Tasks.Task MAsync()
+ async Task MAsync()
{
await foreach (var n in new int[] { })
{
@@ -1277,9 +1285,11 @@ void M()
}
}
}",
-@"class C
+@"using System.Threading.Tasks;
+
+class C
{
- async System.Threading.Tasks.Task MAsync()
+ async Task MAsync()
{
await foreach (var (a, b) in new(int, int)[] { })
{
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs
index ac43c9300e32e..46d7151fa5d2d 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs
@@ -7,11 +7,13 @@
using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.Emit;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
+ [UseExportProvider]
public class ActiveStatementTests_Methods : EditingTestBase
{
#region Methods
@@ -43,12 +45,17 @@ static void Main(string[] args)
}
";
- // TODO (bug 755959): better deleted active statement span
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.method));
+ EditAndContinueValidation.VerifySemantics(
+ new[] { edits },
+ new[]
+ {
+ DocumentResults(
+ active,
+ diagnostics: new[] { Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.method, "Goo(int)")) })
+ });
}
[Fact]
@@ -550,7 +557,7 @@ class C
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "get"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "get", FeaturesResources.code));
}
[Fact]
@@ -575,7 +582,7 @@ public void Property_BlockBodyToExpressionBody2()
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, "int P", CSharpFeaturesResources.property_setter));
+ Diagnostic(RudeEditKind.Delete, "int P", DeletedSymbolDisplay(CSharpFeaturesResources.property_setter, "P.set")));
}
[Fact]
@@ -601,7 +608,7 @@ class C
// Can be improved with https://github.com/dotnet/roslyn/issues/22696
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "int P"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "int P", FeaturesResources.code));
}
#endregion
@@ -654,7 +661,7 @@ public void Indexer_BlockBodyToExpressionBody2()
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, "int this[int a]", CSharpFeaturesResources.indexer_setter));
+ Diagnostic(RudeEditKind.Delete, "int this[int a]", DeletedSymbolDisplay(CSharpFeaturesResources.indexer_setter, "this[int].set")));
}
[Fact]
@@ -756,9 +763,10 @@ public T this[int i]
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
+ // Rude edits of active statements (AS:1) are not reported if the top-level edits are rude.
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.ActiveStatementUpdate, @"stringCollection[1] = ""hello"";"),
- Diagnostic(RudeEditKind.GenericTypeUpdate, "set", CSharpFeaturesResources.indexer_setter));
+ Diagnostic(RudeEditKind.GenericTypeUpdate, "set", CSharpFeaturesResources.indexer_setter),
+ Diagnostic(RudeEditKind.ActiveStatementUpdate, "stringCollection[1] = \"hello\";"));
}
[Fact]
@@ -858,9 +866,10 @@ public T this[int i]
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
+ // Rude edits of active statements (AS:1) are not reported if the top-level edits are rude.
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.ActiveStatementUpdate, "Console.WriteLine(stringCollection[1]);"),
- Diagnostic(RudeEditKind.GenericTypeUpdate, "get", CSharpFeaturesResources.indexer_getter));
+ Diagnostic(RudeEditKind.GenericTypeUpdate, "get", CSharpFeaturesResources.indexer_getter),
+ Diagnostic(RudeEditKind.ActiveStatementUpdate, "Console.WriteLine(stringCollection[1]);"));
}
[Fact]
@@ -959,7 +968,7 @@ public T this[int i]
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
[Fact]
@@ -1058,7 +1067,7 @@ public T this[int i]
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
#endregion
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
index 2fc405947deb6..3f5d01ca493bf 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
@@ -9,11 +9,15 @@
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.EditAndContinue.UnitTests;
using Microsoft.VisualStudio.Debugger.Contracts.EditAndContinue;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
+using Microsoft.CodeAnalysis.Emit;
+using Microsoft.CodeAnalysis.CSharp.UnitTests;
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
+ [UseExportProvider]
public class ActiveStatementTests : EditingTestBase
{
#region Update
@@ -240,7 +244,7 @@ static void Goo(int a)
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
// TODO (tomat): considering a change
@@ -365,20 +369,20 @@ static void Goo(int a)
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "case 2:"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "default:"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "while (true)"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "do"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "for (int i = 0; i < 10; i++ )"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "foreach (var i in new[] { 1, 2 })"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "using ( var z = new C() )"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "fixed ( char* p = \"s\" )"),
- Diagnostic(RudeEditKind.DeleteActiveStatement, "label"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "case 2:", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "default:", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "while (true)", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "do", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "for (int i = 0; i < 10; i++ )", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "foreach (var i in new[] { 1, 2 })", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "using ( var z = new C() )", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "fixed ( char* p = \"s\" )", FeaturesResources.code),
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "label", FeaturesResources.code));
}
[Fact]
@@ -588,7 +592,7 @@ static void Goo(int a)
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
[WorkItem(755959, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/755959")]
@@ -648,7 +652,8 @@ static void Main(String[] args)
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, null, FeaturesResources.namespace_));
+ Diagnostic(RudeEditKind.Delete, null, FeaturesResources.namespace_),
+ Diagnostic(RudeEditKind.Delete, null, DeletedSymbolDisplay(FeaturesResources.class_, "N.C")));
}
#endregion
@@ -1310,6 +1315,19 @@ class C
edits.VerifyRudeDiagnostics(active);
}
+ [Fact]
+ public void InstanceConstructor_DeleteParameterless()
+ {
+ var src1 = "partial class C { public C() { System.Console.WriteLine(1); } }";
+ var src2 = "partial class C { }";
+
+ var edits = GetTopEdits(src1, src2);
+ var active = GetActiveStatements(src1, src2);
+
+ edits.VerifyRudeDiagnostics(active,
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "partial class C", DeletedSymbolDisplay(FeaturesResources.constructor, "C()")));
+ }
+
#endregion
#region Field and Property Initializers
@@ -2087,8 +2105,8 @@ public C() {}
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.field));
+ edits.VerifySemanticDiagnostics(active,
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.field, "a")));
}
[Fact]
@@ -2221,9 +2239,9 @@ public C() {}
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- edits.VerifyRudeDiagnostics(active,
+ edits.VerifySemanticDiagnostics(active,
Diagnostic(RudeEditKind.Move, "int c", FeaturesResources.field),
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.field));
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.field, "a")));
}
[Fact]
@@ -2272,8 +2290,8 @@ class C
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.field));
+ edits.VerifySemanticDiagnostics(active,
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.field, "a")));
}
[Fact]
@@ -2294,8 +2312,8 @@ class C
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.auto_property));
+ edits.VerifySemanticDiagnostics(active,
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.auto_property, "a")));
}
#endregion
@@ -4292,7 +4310,7 @@ static void Main(string[] args)
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "for (; i < 10 ; i++)"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "for (; i < 10 ; i++)", FeaturesResources.code));
}
[Fact]
@@ -4470,7 +4488,7 @@ static void Main(string[] args)
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "for (int i = 1; ; i++ )"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "for (int i = 1; ; i++ )", FeaturesResources.code));
}
[Fact]
@@ -6077,12 +6095,12 @@ class C
{
public static int Main()
{
- return F() switch
+ return F() switch
{
int a when F1() => F2(),
bool b => F3(),
_ => F4()
- };
+ };
}
}";
@@ -6172,18 +6190,17 @@ public void SwitchExpression_NestedInGoverningExpression()
var src1 = @"
class C
{
- public static int Main() => (F() switch { 0 => 1, _ => 2 }) switch { 1 => 10, _ => 20 };
+ public static int Main() => (F() switch { 0 => 1, _ => 2 }) switch { 1 => 10, _ => 20 };
}";
var src2 = @"
class C
{
- public static int Main() => (G() switch { 0 => 10, _ => 20 }) switch { 10 => 100, _ => 200 };
+ public static int Main() => (G() switch { 0 => 10, _ => 20 }) switch { 10 => 100, _ => 200 };
}";
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.ActiveStatementUpdate, "switch { 0 => 10, _ => 20 }"),
Diagnostic(RudeEditKind.SwitchExpressionUpdate, "switch", FeaturesResources.method),
Diagnostic(RudeEditKind.SwitchExpressionUpdate, "switch", FeaturesResources.method));
}
@@ -6704,7 +6721,7 @@ static void Main()
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
[Fact]
@@ -6786,7 +6803,7 @@ static void Main()
var active = GetActiveStatements(src1, src2);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
[Fact]
@@ -8488,18 +8505,20 @@ static void Main(string[] args)
public void Lambdas_ExpressionToDelegate()
{
var src1 = @"
+using System;
class C
{
- static void Main(string[] args)
+ static void Main()
{
Func f = a => 1;
}
}
";
var src2 = @"
+using System;
class C
{
- static void Main(string[] args)
+ static void Main()
{
Func f = delegate(int a) { return 1; };
}
@@ -8542,18 +8561,20 @@ static void Main(string[] args)
public void Lambdas_DelegateToExpression()
{
var src1 = @"
+using System;
class C
{
- static void Main(string[] args)
+ static void Main()
{
Func f = delegate(int a) { return 1; };
}
}
";
var src2 = @"
+using System;
class C
{
- static void Main(string[] args)
+ static void Main()
{
Func f = a => 1;
}
@@ -8569,18 +8590,20 @@ static void Main(string[] args)
public void Lambdas_StatementsToDelegate()
{
var src1 = @"
+using System;
class C
{
- static void Main(string[] args)
+ static void Main()
{
Func f = a => { return 1; };
}
}
";
var src2 = @"
+using System;
class C
{
- static void Main(string[] args)
+ static void Main()
{
Func f = delegate(int a) { return 2; };
}
@@ -9547,6 +9570,9 @@ static async void F()
public void LambdaToAsyncLambda_WithActiveStatement()
{
var src1 = @"
+using System;
+using System.Threading.Tasks;
+
class C
{
static void F()
@@ -9560,6 +9586,9 @@ static void F()
}
";
var src2 = @"
+using System;
+using System.Threading.Tasks;
+
class C
{
static void F()
@@ -9583,6 +9612,8 @@ static void F()
public void LambdaToAsyncLambda_WithActiveStatement_NoAwait()
{
var src1 = @"
+using System;
+
class C
{
static void F()
@@ -9592,6 +9623,8 @@ static void F()
}
";
var src2 = @"
+using System;
+
class C
{
static void F()
@@ -9705,20 +9738,24 @@ static void F()
public void AnonymousFunctionToAsyncAnonymousFunction_WithActiveStatement_NoAwait()
{
var src1 = @"
+using System.Threading.Tasks;
+
class C
{
static void F()
{
- var f = new Action(delegate() { Console.WriteLine(1); });
+ var f = new Func(delegate() { Console.WriteLine(1); return Task.CompletedTask; });
}
}
";
var src2 = @"
+using System.Threading.Tasks;
+
class C
{
static async void F()
{
- var f = new Action(async delegate() { Console.WriteLine(1); });
+ var f = new Func(async delegate() { Console.WriteLine(1); });
}
}
";
@@ -10495,6 +10532,62 @@ static void F()
#endregion
+ #region Partial Types
+
+ [Fact]
+ public void InsertDeleteMethod_Inactive()
+ {
+ // Moving inactive method declaration in a file with active statements.
+
+ var srcA1 = "partial class C { void F1() { System.Console.WriteLine(1); } }";
+ var srcB1 = "partial class C { void F2() { } }";
+ var srcA2 = "partial class C { void F1() { System.Console.WriteLine(1); } void F2() { } }";
+ var srcB2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ activeStatements: GetActiveStatements(srcA1, srcA2),
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F2")),
+ }),
+ DocumentResults(
+ activeStatements: GetActiveStatements(srcB1, srcB2))
+ });
+ }
+
+ [Fact, WorkItem(51177, "https://github.com/dotnet/roslyn/issues/51177")]
+ public void InsertDeleteMethod_Active()
+ {
+ // Moving active method declaration in a file with active statements.
+ // TODO: this is currently a rude edit
+
+ var srcA1 = "partial class C { }";
+ var srcB1 = "partial class C { void F() { System.Console.WriteLine(1); } }";
+ var srcA2 = "partial class C { void F() { System.Console.WriteLine(1); } }";
+ var srcB2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ activeStatements: GetActiveStatements(srcA1, srcA2),
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")),
+ }),
+ DocumentResults(
+ activeStatements: GetActiveStatements(srcB1, srcB2),
+ diagnostics: new[] { Diagnostic(RudeEditKind.DeleteActiveStatement, "partial class C", DeletedSymbolDisplay(FeaturesResources.method, "F()")) })
+ });
+ }
+
+ #endregion
+
#region Misc
[Fact]
@@ -10516,8 +10609,8 @@ static void Goo(int a)
var src2 = @"";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, null, FeaturesResources.class_));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, null, DeletedSymbolDisplay(FeaturesResources.class_, "C")));
}
[Fact]
@@ -10587,7 +10680,7 @@ public static void F()
active.OldStatements[0] = active.OldStatements[0].WithFlags(ActiveStatementFlags.PartiallyExecuted | ActiveStatementFlags.IsLeafFrame);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.PartiallyExecutedActiveStatementDelete, "{"));
+ Diagnostic(RudeEditKind.PartiallyExecutedActiveStatementDelete, "{", FeaturesResources.code));
}
[Fact]
@@ -10614,7 +10707,7 @@ public static void F()
active.OldStatements[0] = active.OldStatements[0].WithFlags(ActiveStatementFlags.IsNonLeafFrame | ActiveStatementFlags.IsLeafFrame);
edits.VerifyRudeDiagnostics(active,
- Diagnostic(RudeEditKind.DeleteActiveStatement, "{"));
+ Diagnostic(RudeEditKind.DeleteActiveStatement, "{", FeaturesResources.code));
}
[Fact]
@@ -10690,7 +10783,7 @@ public static void H(int x)
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
- var validator = CSharpEditAndContinueTestHelpers.CreateInstance(node =>
+ var validator = new CSharpEditAndContinueTestHelpers(faultInjector: node =>
{
if (node.Parent is MethodDeclarationSyntax methodDecl && methodDecl.Identifier.Text == "G")
{
@@ -10702,7 +10795,10 @@ public static void H(int x)
Diagnostic(RudeEditKind.MemberBodyTooBig, "public static void G()", FeaturesResources.method) :
Diagnostic(RudeEditKind.MemberBodyInternalError, "public static void G()", FeaturesResources.method);
- validator.VerifyRudeDiagnostics(edits, active, new[] { expectedDiagnostic });
+ validator.VerifySemantics(
+ new[] { edits },
+ TargetFramework.NetCoreApp,
+ new[] { DocumentResults(diagnostics: new[] { expectedDiagnostic }) });
}
#endregion
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs
index e1d2f3da6f9ce..a6f68489a40e9 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/CSharpEditAndContinueAnalyzerTests.cs
@@ -292,8 +292,8 @@ public static void Main()
var result = await analyzer.AnalyzeDocumentAsync(oldProject, baseActiveStatements, newDocument, ImmutableArray.Empty, CancellationToken.None);
Assert.True(result.HasChanges);
- Assert.True(result.SemanticEdits[0].PreserveLocalVariables);
var syntaxMap = result.SemanticEdits[0].SyntaxMap;
+ Assert.NotNull(syntaxMap);
var newStatementSpan = result.ActiveStatements[0].Span;
var newStatementTextSpan = newText.Lines.GetTextSpan(newStatementSpan);
@@ -685,13 +685,16 @@ public static void Main()
}
";
var source2 = @"
+class D
+{
+}
";
using var workspace = TestWorkspace.CreateCSharp(source1, composition: s_composition);
- var oldProject = workspace.CurrentSolution.Projects.Single();
- var newDocId = DocumentId.CreateNewId(oldProject.Id);
var oldSolution = workspace.CurrentSolution;
+ var oldProject = oldSolution.Projects.Single();
+ var newDocId = DocumentId.CreateNewId(oldProject.Id);
var newSolution = oldSolution.AddDocument(newDocId, "goo.cs", SourceText.From(source2));
workspace.TryApplyChanges(newSolution);
@@ -715,8 +718,7 @@ public static void Main()
}
Assert.True(result.IsSingle());
- Assert.Equal(1, result.Single().RudeEditErrors.Count());
- Assert.Equal(RudeEditKind.InsertFile, result.Single().RudeEditErrors.Single().Kind);
+ Assert.Empty(result.Single().RudeEditErrors);
}
[Theory, CombinatorialData]
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/CSharpEditAndContinueTestHelpers.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/CSharpEditAndContinueTestHelpers.cs
index 802f37365d791..206cbef8f3b8c 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/CSharpEditAndContinueTestHelpers.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/CSharpEditAndContinueTestHelpers.cs
@@ -5,39 +5,28 @@
#nullable disable
using System;
-using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Symbols;
-using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.Differencing;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.EditAndContinue.UnitTests;
using Microsoft.CodeAnalysis.Text;
-using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
internal sealed class CSharpEditAndContinueTestHelpers : EditAndContinueTestHelpers
{
- private readonly ImmutableArray _fxReferences;
private readonly CSharpEditAndContinueAnalyzer _analyzer;
- public CSharpEditAndContinueTestHelpers(TargetFramework targetFramework, Action faultInjector = null)
+ public CSharpEditAndContinueTestHelpers(Action faultInjector = null)
{
- _fxReferences = TargetFrameworkUtil.GetReferences(targetFramework);
_analyzer = new CSharpEditAndContinueAnalyzer(faultInjector);
}
- internal static CSharpEditAndContinueTestHelpers CreateInstance(Action faultInjector = null)
- => new CSharpEditAndContinueTestHelpers(TargetFramework.Mscorlib46Extended, faultInjector);
-
- internal static CSharpEditAndContinueTestHelpers CreateInstance40(Action faultInjector = null)
- => new CSharpEditAndContinueTestHelpers(TargetFramework.Mscorlib40AndSystemCore, faultInjector);
-
public override AbstractEditAndContinueAnalyzer Analyzer => _analyzer;
-
- public override Compilation CreateLibraryCompilation(string name, IEnumerable trees)
- => CSharpCompilation.Create("New", trees, _fxReferences, TestOptions.UnsafeReleaseDll);
+ public override string LanguageName => LanguageNames.CSharp;
+ public override TreeComparer TopSyntaxComparer => SyntaxComparer.TopLevel;
public override SyntaxTree ParseText(string source)
=> SyntaxFactory.ParseSyntaxTree(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview));
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs
index f4f6a74a1bea7..b45ad8c484eaa 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs
@@ -21,7 +21,7 @@ internal static void VerifyUnchangedDocument(
string source,
ActiveStatementsDescription description)
{
- CSharpEditAndContinueTestHelpers.CreateInstance().VerifyUnchangedDocument(
+ new CSharpEditAndContinueTestHelpers().VerifyUnchangedDocument(
ActiveStatementsDescription.ClearTags(source),
description.OldStatements,
description.NewSpans,
@@ -40,7 +40,7 @@ internal static void VerifyRudeDiagnostics(
ActiveStatementsDescription description,
params RudeEditDiagnosticDescription[] expectedDiagnostics)
{
- CSharpEditAndContinueTestHelpers.CreateInstance().VerifyRudeDiagnostics(
+ VerifySemanticDiagnostics(
editScript,
description,
expectedDiagnostics);
@@ -52,7 +52,7 @@ internal static void VerifyLineEdits(
IEnumerable expectedNodeUpdates,
params RudeEditDiagnosticDescription[] expectedDiagnostics)
{
- CSharpEditAndContinueTestHelpers.CreateInstance().VerifyLineEdits(
+ new CSharpEditAndContinueTestHelpers().VerifyLineEdits(
editScript,
expectedLineEdits,
expectedNodeUpdates,
@@ -65,7 +65,17 @@ internal static void VerifySemanticDiagnostics(
{
VerifySemantics(
new[] { editScript },
- expectedDiagnostics: expectedDiagnostics);
+ new[] { new DocumentAnalysisResultsDescription(diagnostics: expectedDiagnostics) });
+ }
+
+ internal static void VerifySemanticDiagnostics(
+ this EditScript editScript,
+ ActiveStatementsDescription activeStatements,
+ params RudeEditDiagnosticDescription[] expectedDiagnostics)
+ {
+ VerifySemantics(
+ new[] { editScript },
+ new[] { new DocumentAnalysisResultsDescription(activeStatements: activeStatements, diagnostics: expectedDiagnostics) });
}
internal static void VerifySemanticDiagnostics(
@@ -75,8 +85,8 @@ internal static void VerifySemanticDiagnostics(
{
VerifySemantics(
new[] { editScript },
- targetFrameworks: targetFrameworks,
- expectedDiagnostics: expectedDiagnostics);
+ new[] { new DocumentAnalysisResultsDescription(diagnostics: expectedDiagnostics) },
+ targetFrameworks: targetFrameworks);
}
internal static void VerifySemantics(
@@ -86,25 +96,24 @@ internal static void VerifySemantics(
{
VerifySemantics(
new[] { editScript },
- activeStatements,
- expectedSemanticEdits: expectedSemanticEdits,
- expectedDiagnostics: null);
+ new[] { new DocumentAnalysisResultsDescription(activeStatements, semanticEdits: expectedSemanticEdits) });
+ }
+
+ internal static void VerifySemantics(
+ this EditScript editScript,
+ params SemanticEditDescription[] expectedSemanticEdits)
+ {
+ VerifySemantics(editScript, ActiveStatementsDescription.Empty, expectedSemanticEdits);
}
internal static void VerifySemantics(
- this EditScript[] editScripts,
- ActiveStatementsDescription? activeStatements = null,
- TargetFramework[]? targetFrameworks = null,
- SemanticEditDescription[]? expectedSemanticEdits = null,
- RudeEditDiagnosticDescription[]? expectedDiagnostics = null)
+ EditScript[] editScripts,
+ DocumentAnalysisResultsDescription[] expected,
+ TargetFramework[]? targetFrameworks = null)
{
foreach (var targetFramework in targetFrameworks ?? new[] { TargetFramework.NetStandard20, TargetFramework.NetCoreApp })
{
- new CSharpEditAndContinueTestHelpers(targetFramework).VerifySemantics(
- editScripts,
- activeStatements,
- expectedSemanticEdits,
- expectedDiagnostics);
+ new CSharpEditAndContinueTestHelpers().VerifySemantics(editScripts, targetFramework, expected);
}
}
}
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs
index 5bb9bdb679f3d..329d1b71c8b5f 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs
@@ -2,16 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#nullable disable
-
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.CodeAnalysis.Differencing;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.EditAndContinue.UnitTests;
-using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.EditAndContinue;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
@@ -39,17 +37,23 @@ internal enum MethodKind
internal static RudeEditDiagnosticDescription Diagnostic(RudeEditKind rudeEditKind, string squiggle, params string[] arguments)
=> new(rudeEditKind, squiggle, arguments, firstLine: null);
- internal static SemanticEditDescription SemanticEdit(SemanticEditKind kind, Func symbolProvider, IEnumerable> syntaxMap)
- {
- Assert.NotNull(syntaxMap);
- return new SemanticEditDescription(kind, symbolProvider, syntaxMap, preserveLocalVariables: true);
- }
+ internal static SemanticEditDescription SemanticEdit(SemanticEditKind kind, Func symbolProvider, IEnumerable>? syntaxMap, string? partialType = null)
+ => new(kind, symbolProvider, (partialType != null) ? c => c.GetMember(partialType) : null, syntaxMap, hasSyntaxMap: syntaxMap != null);
+
+ internal static SemanticEditDescription SemanticEdit(SemanticEditKind kind, Func symbolProvider, string? partialType = null, bool preserveLocalVariables = false)
+ => new(kind, symbolProvider, (partialType != null) ? c => c.GetMember(partialType) : null, syntaxMap: null, preserveLocalVariables);
+
+ internal static string DeletedSymbolDisplay(string kind, string displayName)
+ => string.Format(FeaturesResources.member_kind_and_name, kind, displayName);
- internal static SemanticEditDescription SemanticEdit(SemanticEditKind kind, Func symbolProvider, bool preserveLocalVariables = false)
- => new(kind, symbolProvider, syntaxMap: null, preserveLocalVariables);
+ internal static DocumentAnalysisResultsDescription DocumentResults(
+ ActiveStatementsDescription? activeStatements = null,
+ SemanticEditDescription[]? semanticEdits = null,
+ RudeEditDiagnosticDescription[]? diagnostics = null)
+ => new(activeStatements, semanticEdits, diagnostics);
private static SyntaxTree ParseSource(string source)
- => CSharpEditAndContinueTestHelpers.CreateInstance().ParseText(ActiveStatementsDescription.ClearTags(source));
+ => new CSharpEditAndContinueTestHelpers().ParseText(ActiveStatementsDescription.ClearTags(source));
internal static EditScript GetTopEdits(string src1, string src2)
{
@@ -63,6 +67,14 @@ internal static EditScript GetTopEdits(string src1, string src2)
return match.GetTreeEdits();
}
+ public static EditScript GetTopEdits(EditScript methodEdits)
+ {
+ var oldMethodSource = methodEdits.Match.OldRoot.ToFullString();
+ var newMethodSource = methodEdits.Match.NewRoot.ToFullString();
+
+ return GetTopEdits(WrapMethodBodyWithClass(oldMethodSource), WrapMethodBodyWithClass(newMethodSource));
+ }
+
///
/// Gets method edits on the current level of the source hierarchy. This means that edits on lower labeled levels of the hierarchy are not expected to be returned.
///
@@ -103,6 +115,8 @@ public static MatchingPairs ToMatchingPairs(Match match)
public static MatchingPairs ToMatchingPairs(IEnumerable> matches)
=> EditAndContinueTestHelpers.ToMatchingPairs(matches);
+#nullable disable
+
internal static BlockSyntax MakeMethodBody(
string bodySource,
MethodKind kind = MethodKind.Regular)
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs
index 57e9be220784e..9e9d146525be9 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs
@@ -9,10 +9,12 @@
using Microsoft.VisualStudio.Debugger.Contracts.EditAndContinue;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.Emit;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
+ [UseExportProvider]
public class LineEditTests : EditingTestBase
{
#region Methods
@@ -1423,5 +1425,44 @@ class C
}
#endregion
+
+ #region Types
+
+ [Fact]
+ public void Type_Reorder1()
+ {
+ var src1 = @"
+class C
+{
+ static int F1() => 1;
+ static int F2() => 1;
+}
+
+class D
+{
+ static int G1() => 1;
+ static int G2() => 1;
+}
+";
+ var src2 = @"
+class D
+{
+ static int G1() => 1;
+ static int G2() => 1;
+}
+
+class C
+{
+ static int F1() => 1;
+ static int F2() => 1;
+}
+";
+ var edits = GetTopEdits(src1, src2);
+ edits.VerifyLineEdits(
+ new[] { new SourceLineUpdate(3, 9), new SourceLineUpdate(4, 10), new SourceLineUpdate(9, 3), new SourceLineUpdate(10, 4) },
+ Array.Empty());
+ }
+
+ #endregion
}
}
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs
index 45411ddddb79c..e863592fd1c4e 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs
@@ -17,6 +17,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
+ [UseExportProvider]
public class StatementEditingTests : EditingTestBase
{
#region Strings
@@ -6813,7 +6814,8 @@ public void LocalFunction_In_Parameter_InsertParameter()
edits.VerifyEdits(
"Update [void M() { void local() { throw null; } }]@13 -> [void M() { void local(in int b) { throw null; } }]@13");
- edits.VerifyRudeDiagnostics();
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.ChangingLambdaParameters, "local", CSharpFeaturesResources.local_function));
}
[Fact]
@@ -6827,7 +6829,8 @@ public void LocalFunction_In_Parameter_Update()
edits.VerifyEdits(
"Update [void M() { void local(int b) { throw null; } }]@13 -> [void M() { void local(in int b) { throw null; } }]@13");
- edits.VerifyRudeDiagnostics();
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.ChangingLambdaParameters, "local", CSharpFeaturesResources.local_function));
}
[Fact]
@@ -7000,9 +7003,8 @@ public void LocalFunction_AddAttribute()
"Insert [A]@3");
// Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "[A]", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "[A]", FeaturesResources.attribute));
}
[Fact]
@@ -7018,9 +7020,8 @@ public void LocalFunction_RemoveAttribute()
"Delete [A]@3");
// Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.attribute));
}
[Fact]
@@ -7034,9 +7035,7 @@ public void LocalFunction_ReorderAttribute()
edits.VerifyEdits("Reorder [B]@6 -> @3");
// Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics();
+ GetTopEdits(edits).VerifyRudeDiagnostics();
}
[Fact]
@@ -7054,9 +7053,7 @@ public void LocalFunction_CombineAttributeLists()
"Delete [B]@6");
// Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(
+ GetTopEdits(edits).VerifyRudeDiagnostics(
Diagnostic(RudeEditKind.Insert, "B", FeaturesResources.attribute),
Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.attribute));
}
@@ -7075,10 +7072,8 @@ public void LocalFunction_SplitAttributeLists()
"Insert [B]@6",
"Delete [B]@6");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "[B]", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "[B]", FeaturesResources.attribute));
}
[Fact]
@@ -7091,10 +7086,8 @@ public void LocalFunction_ChangeAttributeListTarget1()
edits.VerifyEdits("Update [[return: A]]@2 -> [[A]]@2");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Update, "[A]", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Update, "[A]", FeaturesResources.attribute));
}
[Fact]
@@ -7107,10 +7100,8 @@ public void LocalFunction_ChangeAttributeListTarget2()
edits.VerifyEdits("Update [[A]]@2 -> [[return: A]]@2");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Update, "return:", CSharpFeaturesResources.attribute_target));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Update, "return:", CSharpFeaturesResources.attribute_target));
}
[Fact]
@@ -7125,10 +7116,8 @@ public void LocalFunction_ReturnType_AddAttribute()
"Insert [[return: A]]@2",
"Insert [A]@11");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "[return: A]", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "[return: A]", FeaturesResources.attribute));
}
[Fact]
@@ -7143,10 +7132,8 @@ public void LocalFunction_ReturnType_RemoveAttribute()
"Delete [[return: A]]@2",
"Delete [A]@11");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.attribute));
}
[Fact]
@@ -7159,10 +7146,7 @@ public void LocalFunction_ReturnType_ReorderAttribute()
edits.VerifyEdits("Reorder [B]@14 -> @11");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics();
+ GetTopEdits(edits).VerifyRudeDiagnostics();
}
[Fact]
@@ -7177,10 +7161,8 @@ public void LocalFunction_Parameter_AddAttribute()
"Insert [[A]]@9",
"Insert [A]@10");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "[A]", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "[A]", FeaturesResources.attribute));
}
[Fact]
@@ -7195,10 +7177,8 @@ public void LocalFunction_Parameter_RemoveAttribute()
"Delete [[A]]@9",
"Delete [A]@10");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Delete, "int i", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "int i", FeaturesResources.attribute));
}
[Fact]
@@ -7211,10 +7191,7 @@ public void LocalFunction_Parameter_ReorderAttribute()
edits.VerifyEdits("Reorder [B]@13 -> @10");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics();
+ GetTopEdits(edits).VerifyRudeDiagnostics();
}
[Fact]
@@ -7229,10 +7206,8 @@ public void LocalFunction_TypeParameter_AddAttribute()
"Insert [[A]]@9",
"Insert [A]@10");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "[A]", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "[A]", FeaturesResources.attribute));
}
[Fact]
@@ -7247,10 +7222,8 @@ public void LocalFunction_TypeParameter_RemoveAttribute()
"Delete [[A]]@9",
"Delete [A]@10");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Delete, "T", FeaturesResources.attribute));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "T", FeaturesResources.attribute));
}
[Fact]
@@ -7263,10 +7236,7 @@ public void LocalFunction_TypeParameter_ReorderAttribute()
edits.VerifyEdits("Reorder [B]@13 -> @10");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics();
+ GetTopEdits(edits).VerifyRudeDiagnostics();
}
[Fact]
@@ -7280,10 +7250,8 @@ public void LocalFunctions_TypeParameter_Insert1()
"Insert []@8",
"Insert [A]@9");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "", FeaturesResources.type_parameter));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "", FeaturesResources.type_parameter));
}
[Fact]
@@ -7297,10 +7265,8 @@ public void LocalFunctions_TypeParameter_Insert2()
"Update []@8 -> []@8",
"Insert [B]@11");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Insert, "B", FeaturesResources.type_parameter));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "B", FeaturesResources.type_parameter));
}
[Fact]
@@ -7314,10 +7280,8 @@ public void LocalFunctions_TypeParameter_Delete1()
"Delete []@8",
"Delete [A]@9");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.type_parameter));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.type_parameter));
}
[Fact]
@@ -7331,10 +7295,8 @@ public void LocalFunctions_TypeParameter_Delete2()
"Update []@8 -> []@8",
"Delete [A]@9");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.type_parameter));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "L", FeaturesResources.type_parameter));
}
[Fact]
@@ -7347,10 +7309,8 @@ public void LocalFunctions_TypeParameter_Update()
edits.VerifyEdits(
"Update [A]@9 -> [B]@9");
- // Get top edits so we can validate rude edits
- edits = GetTopEdits(WrapMethodBodyWithClass(src1), WrapMethodBodyWithClass(src2));
-
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Renamed, "B", FeaturesResources.type_parameter));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Renamed, "B", FeaturesResources.type_parameter));
}
[Fact]
@@ -7363,7 +7323,8 @@ public void LocalFunctions_TypeParameter_Reorder()
edits.VerifyEdits(
"Reorder [B]@11 -> @9");
- edits.VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Move, "B", FeaturesResources.type_parameter));
+ GetTopEdits(edits).VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Move, "B", FeaturesResources.type_parameter));
}
[Fact]
@@ -7377,10 +7338,11 @@ public void LocalFunctions_TypeParameter_ReorderAndUpdate()
"Reorder [B]@11 -> @9",
"Update [A]@9 -> [C]@11");
- edits.VerifyRudeDiagnostics(
+ GetTopEdits(edits).VerifyRudeDiagnostics(
Diagnostic(RudeEditKind.Move, "B", FeaturesResources.type_parameter),
Diagnostic(RudeEditKind.Renamed, "C", FeaturesResources.type_parameter));
}
+
#endregion
#region Queries
@@ -8908,13 +8870,9 @@ static IEnumerable F()
";
var edits = GetTopEdits(src1, src2);
- CSharpEditAndContinueTestHelpers.CreateInstance40().VerifySemantics(
- new[] { edits },
- ActiveStatementsDescription.Empty,
- expectedDiagnostics: new[]
- {
- Diagnostic(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, "static IEnumerable F()", "System.Runtime.CompilerServices.IteratorStateMachineAttribute")
- });
+ edits.VerifySemanticDiagnostics(
+ targetFrameworks: new[] { TargetFramework.Mscorlib40AndSystemCore },
+ Diagnostic(RudeEditKind.UpdatingStateMachineMethodMissingAttribute, "static IEnumerable F()", "System.Runtime.CompilerServices.IteratorStateMachineAttribute"));
}
[Fact]
@@ -8944,7 +8902,8 @@ static IEnumerable F()
";
var edits = GetTopEdits(src1, src2);
- CSharpEditAndContinueTestHelpers.CreateInstance40().VerifySemantics(new[] { edits });
+ edits.VerifySemanticDiagnostics(
+ targetFrameworks: new[] { TargetFramework.Mscorlib40AndSystemCore });
}
#endregion
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs
index ee0f7ee51e5c2..95f06a78ca88c 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/SyntaxComparerTests.cs
@@ -7,11 +7,13 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Differencing;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
+ [UseExportProvider]
public class SyntaxComparerTests
{
private static SyntaxNode MakeLiteral(int n)
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs
index 0f56eb6ba6fba..80ab9bb7580e6 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs
@@ -4,8 +4,8 @@
#nullable disable
+using System;
using System.Linq;
-using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.CodeAnalysis.EditAndContinue;
@@ -17,6 +17,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
+ [UseExportProvider]
public class TopLevelEditingTests : EditingTestBase
{
#region Usings
@@ -39,20 +40,21 @@ public void UsingDelete1()
public void UsingDelete2()
{
var src1 = @"
-using System.Diagnostics;
+using D = System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
";
var src2 = @"
-using System.Diagnostics;
using System.Collections.Generic;
";
var edits = GetTopEdits(src1, src2);
edits.VerifyEdits(
- "Delete [using System.Collections;]@29");
+ "Delete [using D = System.Diagnostics;]@2",
+ "Delete [using System.Collections;]@33");
edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, null, CSharpFeaturesResources.using_directive),
Diagnostic(RudeEditKind.Delete, null, CSharpFeaturesResources.using_directive));
}
@@ -60,20 +62,21 @@ public void UsingDelete2()
public void UsingInsert()
{
var src1 = @"
-using System.Diagnostics;
using System.Collections.Generic;
";
var src2 = @"
-using System.Diagnostics;
+using D = System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
";
var edits = GetTopEdits(src1, src2);
edits.VerifyEdits(
- "Insert [using System.Collections;]@29");
+ "Insert [using D = System.Diagnostics;]@2",
+ "Insert [using System.Collections;]@33");
edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "using D = System.Diagnostics;", CSharpFeaturesResources.using_directive),
Diagnostic(RudeEditKind.Insert, "using System.Collections;", CSharpFeaturesResources.using_directive));
}
@@ -217,6 +220,55 @@ namespace N
#endregion
+ #region Extern Alias
+
+ [Fact]
+ public void ExternAliasUpdate()
+ {
+ var src1 = "extern alias X;";
+ var src2 = "extern alias Y;";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Update [extern alias X;]@0 -> [extern alias Y;]@0");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Update, "extern alias Y;", CSharpFeaturesResources.extern_alias));
+ }
+
+ [Fact]
+ public void ExternAliasInsert()
+ {
+ var src1 = "";
+ var src2 = "extern alias Y;";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Insert [extern alias Y;]@0");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "extern alias Y;", CSharpFeaturesResources.extern_alias));
+ }
+
+ [Fact]
+ public void ExternAliasDelete()
+ {
+ var src1 = "extern alias Y;";
+ var src2 = "";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Delete [extern alias Y;]@0");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, null, CSharpFeaturesResources.extern_alias));
+ }
+
+ #endregion
+
#region Attributes
[Fact]
@@ -735,6 +787,7 @@ public void InterfaceInsert()
public interface I
{
void F();
+ static void G() {}
}";
var edits = GetTopEdits(src1, src2);
@@ -867,7 +920,7 @@ public class SubClass : BaseClass, IConflict
[WorkItem(37128, "https://github.com/dotnet/roslyn/issues/37128")]
[Fact]
- public void Interface_AddMembersWithImplementation()
+ public void Interface_InsertMembers()
{
var src1 = @"
using System;
@@ -915,42 +968,407 @@ event Action VirtualEvent { add { } remove { } }
abstract event Action AbstractEvent;
sealed event Action NonVirtualEvent { add { } remove { } }
+ abstract class C { }
interface J { }
+ enum E { }
+ delegate void D();
}
";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
+ // TODO: InsertIntoInterface errors are reported due to https://github.com/dotnet/roslyn/issues/37128.
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.InsertIntoInterface, "static void StaticMethod()", FeaturesResources.method),
Diagnostic(RudeEditKind.InsertVirtual, "void VirtualMethod1()", FeaturesResources.method),
Diagnostic(RudeEditKind.InsertVirtual, "virtual void VirtualMethod2()", FeaturesResources.method),
Diagnostic(RudeEditKind.InsertVirtual, "abstract void AbstractMethod()", FeaturesResources.method),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "sealed void NonVirtualMethod()", FeaturesResources.method),
Diagnostic(RudeEditKind.InsertOperator, "public static int operator +(I a, I b)", FeaturesResources.operator_),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "static int StaticProperty1", FeaturesResources.auto_property),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "static int StaticProperty2", FeaturesResources.property_),
Diagnostic(RudeEditKind.InsertVirtual, "virtual int VirtualProperty1", FeaturesResources.auto_property),
Diagnostic(RudeEditKind.InsertVirtual, "virtual int VirtualProperty2", FeaturesResources.auto_property),
Diagnostic(RudeEditKind.InsertVirtual, "int VirtualProperty3", FeaturesResources.auto_property),
Diagnostic(RudeEditKind.InsertVirtual, "int VirtualProperty4", FeaturesResources.auto_property),
Diagnostic(RudeEditKind.InsertVirtual, "abstract int AbstractProperty1", FeaturesResources.property_),
Diagnostic(RudeEditKind.InsertVirtual, "abstract int AbstractProperty2", FeaturesResources.property_),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "sealed int NonVirtualProperty", FeaturesResources.property_),
Diagnostic(RudeEditKind.InsertVirtual, "int this[byte virtualIndexer]", FeaturesResources.indexer_),
Diagnostic(RudeEditKind.InsertVirtual, "int this[sbyte virtualIndexer]", FeaturesResources.indexer_),
Diagnostic(RudeEditKind.InsertVirtual, "virtual int this[ushort virtualIndexer]", FeaturesResources.indexer_),
Diagnostic(RudeEditKind.InsertVirtual, "virtual int this[short virtualIndexer]", FeaturesResources.indexer_),
Diagnostic(RudeEditKind.InsertVirtual, "abstract int this[uint abstractIndexer]", FeaturesResources.indexer_),
Diagnostic(RudeEditKind.InsertVirtual, "abstract int this[int abstractIndexer]", FeaturesResources.indexer_),
- Diagnostic(RudeEditKind.InsertVirtual, "event Action VirtualEvent", FeaturesResources.event_),
- Diagnostic(RudeEditKind.InsertVirtual, "abstract event Action AbstractEvent", CSharpFeaturesResources.event_field),
- // TODO: The following errors are reported due to https://github.com/dotnet/roslyn/issues/37128.
- Diagnostic(RudeEditKind.InsertIntoInterface, "static int StaticField = 10", FeaturesResources.field),
- Diagnostic(RudeEditKind.InsertIntoInterface, "static void StaticMethod()", FeaturesResources.method),
- Diagnostic(RudeEditKind.InsertIntoInterface, "sealed void NonVirtualMethod()", FeaturesResources.method),
- Diagnostic(RudeEditKind.InsertIntoInterface, "static int StaticProperty1", FeaturesResources.auto_property),
- Diagnostic(RudeEditKind.InsertIntoInterface, "static int StaticProperty2", FeaturesResources.property_),
- Diagnostic(RudeEditKind.InsertIntoInterface, "sealed int NonVirtualProperty", FeaturesResources.property_),
Diagnostic(RudeEditKind.InsertIntoInterface, "sealed int this[ulong nonVirtualIndexer]", FeaturesResources.indexer_),
Diagnostic(RudeEditKind.InsertIntoInterface, "sealed int this[long nonVirtualIndexer]", FeaturesResources.indexer_),
- Diagnostic(RudeEditKind.InsertIntoInterface, "static event Action StaticEvent", CSharpFeaturesResources.event_field),
Diagnostic(RudeEditKind.InsertIntoInterface, "static event Action StaticEvent2", FeaturesResources.event_),
- Diagnostic(RudeEditKind.InsertIntoInterface, "sealed event Action NonVirtualEvent", FeaturesResources.event_));
+ Diagnostic(RudeEditKind.InsertVirtual, "event Action VirtualEvent", FeaturesResources.event_),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "sealed event Action NonVirtualEvent", FeaturesResources.event_),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "StaticField = 10", FeaturesResources.field),
+ Diagnostic(RudeEditKind.InsertIntoInterface, "StaticEvent", CSharpFeaturesResources.event_field),
+ Diagnostic(RudeEditKind.InsertVirtual, "AbstractEvent", CSharpFeaturesResources.event_field));
+ }
+
+ [Fact]
+ public void Interface_InsertDelete()
+ {
+ var srcA1 = @"
+interface I
+{
+ static void M() { }
+}
+";
+ var srcB1 = @"
+";
+
+ var srcA2 = @"
+";
+ var srcB2 = @"
+interface I
+{
+ static void M() { }
+}
+";
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("M"))
+ }),
+ });
+ }
+
+ [Fact]
+ public void GenericType_InsertMembers()
+ {
+ var src1 = @"
+using System;
+class C
+{
+}
+";
+ var src2 = @"
+using System;
+class C
+{
+ void M() {}
+ int P1 { get; set; }
+ int P2 { get => 1; set {} }
+ int this[int i] { get => 1; set {} }
+ event Action E { add {} remove {} }
+ event Action EF;
+ int F1, F2;
+
+ enum E {}
+ interface I {}
+ class D {}
+}
+";
+ var edits = GetTopEdits(src1, src2);
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "void M()", FeaturesResources.method),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "int P1", FeaturesResources.auto_property),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "int P2", FeaturesResources.auto_property),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "int this[int i]", FeaturesResources.indexer_),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "event Action E", FeaturesResources.event_),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "EF", CSharpFeaturesResources.event_field),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "F1", FeaturesResources.field),
+ Diagnostic(RudeEditKind.InsertIntoGenericType, "F2", FeaturesResources.field));
+ }
+
+ [Fact]
+ public void Type_Delete()
+ {
+ var src1 = @"
+class C { void F() {} }
+struct S { void F() {} }
+interface I { void F() {} }
+";
+ var src2 = "";
+
+ GetTopEdits(src1, src2).VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, null, DeletedSymbolDisplay(FeaturesResources.class_, "C")),
+ Diagnostic(RudeEditKind.Delete, null, DeletedSymbolDisplay(CSharpFeaturesResources.struct_, "S")),
+ Diagnostic(RudeEditKind.Delete, null, DeletedSymbolDisplay(FeaturesResources.interface_, "I")));
+ }
+
+ [Fact]
+ public void PartialType_Delete()
+ {
+ var srcA1 = "partial class C { void F() {} void M() { } }";
+ var srcB1 = "partial class C { void G() {} }";
+ var srcA2 = "";
+ var srcB2 = "partial class C { void G() {} void M() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Delete, null, DeletedSymbolDisplay(FeaturesResources.method, "C.F()")) }),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("M")),
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialType_InsertFirstDeclaration()
+ {
+ var src1 = "";
+ var src2 = "partial class C { void F() {} }";
+
+ GetTopEdits(src1, src2).VerifySemantics(
+ ActiveStatementsDescription.Empty,
+ new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C"), preserveLocalVariables: false) });
+ }
+
+ [Fact]
+ public void PartialType_InsertSecondDeclaration()
+ {
+ var srcA1 = "partial class C { void F() {} }";
+ var srcB1 = "";
+ var srcA2 = "partial class C { void F() {} }";
+ var srcB2 = "partial class C { void G() {} }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("G"), preserveLocalVariables: false)
+ }),
+ });
+ }
+
+ [Fact]
+ public void Type_DeleteInsert()
+ {
+ var srcA1 = @"
+class C { void F() {} }
+struct S { void F() {} }
+interface I { void F() {} }
+";
+ var srcB1 = "";
+
+ var srcA2 = srcB1;
+ var srcB2 = srcA1;
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ 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")),
+ })
+ });
+ }
+
+ [Fact]
+ public void GenericType_DeleteInsert()
+ {
+ var srcA1 = @"
+class C { void F() {} }
+struct S { void F() {} }
+interface I { void F() {} }
+";
+ var srcB1 = "";
+
+ var srcA2 = srcB1;
+ var srcB2 = srcA1;
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.GenericTypeTriviaUpdate, "void F()", FeaturesResources.method),
+ Diagnostic(RudeEditKind.GenericTypeTriviaUpdate, "void F()", FeaturesResources.method),
+ Diagnostic(RudeEditKind.GenericTypeTriviaUpdate, "void F()", FeaturesResources.method),
+ })
+ });
+ }
+
+ [Fact]
+ public void Type_DeleteInsert_NonInsertableMembers()
+ {
+ var srcA1 = @"
+abstract class C
+{
+ public abstract void AbstractMethod();
+ public virtual void VirtualMethod() {}
+ public override string ToString() => null;
+ public void I.G() {}
+}
+
+interface I
+{
+ void G();
+ void F() {}
+}
+";
+ var srcB1 = "";
+
+ var srcA2 = srcB1;
+ var srcB2 = srcA1;
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ 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("F")),
+ })
+ });
+ }
+
+ [Fact]
+ public void Type_DeleteInsert_DataMembers()
+ {
+ var srcA1 = @"
+class C
+{
+ public int x = 1;
+ public int y = 2;
+ public int P { get; set; } = 3;
+ public event System.Action E = new System.Action(null);
+}
+";
+ var srcB1 = "";
+
+ var srcA2 = "";
+ var srcB2 = @"
+class C
+{
+ public int x = 1;
+ public int y = 2;
+ public int P { get; set; } = 3;
+ public event System.Action E = new System.Action(null);
+}
+";
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true),
+ })
+ });
+ }
+
+ [Fact]
+ public void Type_DeleteInsert_DataMembers_PartialSplit()
+ {
+ var srcA1 = @"
+class C
+{
+ public int x = 1;
+ public int y = 2;
+ public int P { get; set; } = 3;
+}
+";
+ var srcB1 = "";
+
+ var srcA2 = @"
+partial class C
+{
+ public int x = 1;
+ public int y = 2;
+}
+";
+ var srcB2 = @"
+partial class C
+{
+ public int P { get; set; } = 3;
+}
+";
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true),
+ })
+ });
+ }
+
+ [Fact]
+ public void Type_DeleteInsert_DataMembers_PartialMerge()
+ {
+ var srcA1 = @"
+partial class C
+{
+ public int x = 1;
+ public int y = 2;
+}
+";
+ var srcB1 = @"
+partial class C
+{
+ public int P { get; set; } = 3;
+}";
+
+ var srcA2 = @"
+class C
+{
+ public int x = 1;
+ public int y = 2;
+ public int P { get; set; } = 3;
+}
+";
+
+ var srcB2 = @"
+";
+ // note that accessors are not updated since they do not have bodies
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true),
+ }),
+
+ DocumentResults()
+ });
}
#endregion
@@ -1276,7 +1694,7 @@ public void EnumMemberDelete()
"Delete [Blue]@18");
edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "enum Color", FeaturesResources.enum_value));
+ Diagnostic(RudeEditKind.Delete, "enum Color", DeletedSymbolDisplay(FeaturesResources.enum_value, "Blue")));
}
[Fact]
@@ -1290,7 +1708,7 @@ public void EnumMemberDelete2()
edits.VerifyEdits("Delete [Blue]@18");
edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "enum Color", FeaturesResources.enum_value));
+ Diagnostic(RudeEditKind.Delete, "enum Color", DeletedSymbolDisplay(FeaturesResources.enum_value, "Blue")));
}
[WorkItem(754916, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/754916"), WorkItem(793197, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/793197")]
@@ -1433,8 +1851,8 @@ public void Delegates_Delete()
"Delete [private delegate void D();]@10",
"Delete [()]@33");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.delegate_));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.delegate_, "D")));
}
[Fact]
@@ -1542,6 +1960,21 @@ public void Delegates_Parameter_Update()
Diagnostic(RudeEditKind.TypeUpdate, "byte a", FeaturesResources.parameter));
}
+ [Fact]
+ public void Delegates_ParameterOptionalParameter_Update()
+ {
+ var src1 = "public delegate int D(int a = 1);";
+ var src2 = "public delegate int D(int a = 2);";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Update [int a = 1]@22 -> [int a = 2]@22");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.InitializerUpdate, "int a = 2", FeaturesResources.parameter));
+ }
+
[Fact]
public void Delegates_Parameter_UpdateModifier()
{
@@ -1934,7 +2367,7 @@ abstract class D
{
public extern D();
- public static extern int P { [DllImport(""msvcrt.dll"")]get; }
+ public static extern int P { [DllImport(""msvcrt.dll"")]get; [DllImport(""msvcrt.dll"")]set; }
[DllImport(""msvcrt.dll"")]
public static extern int puts(string c);
@@ -1950,7 +2383,7 @@ abstract class D
var edits = GetTopEdits(src1, src2);
// Adding P/Invoke is not supported by the CLR.
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertExtern, "public extern D()", FeaturesResources.constructor),
Diagnostic(RudeEditKind.InsertExtern, "public static extern int P", FeaturesResources.property_),
Diagnostic(RudeEditKind.InsertExtern, "public static extern int puts(string c)", FeaturesResources.method),
@@ -2023,8 +2456,8 @@ public void NestedClass_MethodDeleteInsert()
"Delete [public void goo() {}]@17",
"Delete [()]@32");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "public class C", FeaturesResources.method));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "public class C", DeletedSymbolDisplay(FeaturesResources.method, "goo()")));
}
[Fact]
@@ -2043,152 +2476,1086 @@ public void NestedClass_ClassDeleteInsert()
Diagnostic(RudeEditKind.Move, "public class X", FeaturesResources.class_));
}
- #endregion
-
- #region Namespaces
+ ///
+ /// A new generic type can be added whether it's nested and inherits generic parameters from the containing type, or top-level.
+ ///
+ [Fact]
+ public void NestedClassGeneric_Insert()
+ {
+ var src1 = @"
+using System;
+class C
+{
+}
+";
+ var src2 = @"
+using System;
+class C
+{
+ class D {}
+ struct S {}
+ enum N {}
+ interface I {}
+ delegate void D();
+}
+
+class D
+{
+
+}
+";
+ var edits = GetTopEdits(src1, src2);
+ edits.VerifyRudeDiagnostics();
+ }
+
+ [Fact]
+ public void NestedEnum_InsertMember()
+ {
+ var src1 = "struct S { enum N { A = 1 } }";
+ var src2 = "struct S { enum N { A = 1, B = 2 } }";
+
+ var edits = GetTopEdits(src1, src2);
+ edits.VerifyEdits(
+ "Update [enum N { A = 1 }]@11 -> [enum N { A = 1, B = 2 }]@11",
+ "Insert [B = 2]@27");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "B = 2", FeaturesResources.enum_value));
+ }
+
+ [Fact, WorkItem(50876, "https://github.com/dotnet/roslyn/issues/50876")]
+ public void NestedEnumInPartialType_InsertDelete()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { enum N { A = 1 } }";
+ var srcA2 = "partial struct S { enum N { A = 1 } }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults()
+ });
+ }
+
+ [Fact, WorkItem(50876, "https://github.com/dotnet/roslyn/issues/50876")]
+ public void NestedEnumInPartialType_InsertDeleteAndUpdateMember()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { enum N { A = 1 } }";
+ var srcA2 = "partial struct S { enum N { A = 2 } }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.InitializerUpdate, "A = 2", FeaturesResources.enum_value),
+ }),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact, WorkItem(50876, "https://github.com/dotnet/roslyn/issues/50876")]
+ public void NestedEnumInPartialType_InsertDeleteAndUpdateBase()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { enum N : uint { A = 1 } }";
+ var srcA2 = "partial struct S { enum N : int { A = 1 } }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.EnumUnderlyingTypeUpdate, "enum N", FeaturesResources.enum_),
+ }),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact, WorkItem(50876, "https://github.com/dotnet/roslyn/issues/50876")]
+ public void NestedEnumInPartialType_InsertDeleteAndInsertMember()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { enum N { A = 1 } }";
+ var srcA2 = "partial struct S { enum N { A = 1, B = 2 } }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Insert, "B = 2", FeaturesResources.enum_value) }),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact]
+ public void NestedDelegateInPartialType_InsertDelete()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { delegate void D(); }";
+ var srcA2 = "partial struct S { delegate void D(); }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ // delegate does not have any user-defined method body and this does not need a PDB update
+ semanticEdits: NoSemanticEdits),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact]
+ public void NestedDelegateInPartialType_InsertDeleteAndChangeSignature()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { delegate void D(); }";
+ var srcA2 = "partial struct S { delegate void D(int x); }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.Insert, "int x", FeaturesResources.parameter)
+ }),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact]
+ public void NestedDelegateInPartialType_InsertDeleteAndChangeOptionalParameterValue()
+ {
+ var srcA1 = "partial struct S { }";
+ var srcB1 = "partial struct S { delegate void D(int x = 1); }";
+ var srcA2 = "partial struct S { delegate void D(int x = 2); }";
+ var srcB2 = "partial struct S { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.InitializerUpdate, "int x = 2", FeaturesResources.parameter)
+ }),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteAndChange()
+ {
+ var srcA1 = "partial struct S { partial class C { void F1() {} } }";
+ var srcB1 = "partial struct S { partial class C { void F2(byte x) {} } }";
+ var srcC1 = "partial struct S { }";
+
+ var srcA2 = "partial struct S { partial class C { void F1() {} } }";
+ var srcB2 = "partial struct S { }";
+ var srcC2 = "partial struct S { partial class C { void F2(int x) {} } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Delete, "partial struct S", DeletedSymbolDisplay(FeaturesResources.method, "F2(byte)")) }),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("S").GetMember("C").GetMember("F2")) })
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteAndChange_BaseType()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "";
+ var srcC1 = "partial class C { }";
+
+ var srcA2 = "";
+ var srcB2 = "partial class C : D { }";
+ var srcC2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.BaseTypeOrInterfaceUpdate, "partial class C", FeaturesResources.class_) }),
+
+ DocumentResults(),
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteAndChange_Attribute()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "";
+ var srcC1 = "partial class C { }";
+
+ var srcA2 = "";
+ var srcB2 = "[A]partial class C { }";
+ var srcC2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Update, "partial class C", FeaturesResources.class_) }),
+
+ DocumentResults(),
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteAndChange_TypeParameter()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "";
+ var srcC1 = "partial class C { }";
+
+ var srcA2 = "";
+ var srcB2 = "partial class C<[A]T> { }";
+ var srcC2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Update, "partial class C<[A]T>", FeaturesResources.class_) }),
+
+ DocumentResults(),
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteAndChange_Constraint()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "";
+ var srcC1 = "partial class C { }";
+
+ var srcA2 = "";
+ var srcB2 = "partial class C where T : new() { }";
+ var srcC2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Update, "partial class C", FeaturesResources.class_) }),
+
+ DocumentResults(),
+ });
+ }
+
+ ///
+ /// Moves partial classes to different files while moving around their attributes and base interfaces.
+ ///
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteRefactor()
+ {
+ var srcA1 = "partial class C : I { void F() { } }";
+ var srcB1 = "[A][B]partial class C : J { void G() { } }";
+ var srcC1 = "";
+ var srcD1 = "";
+
+ var srcA2 = "";
+ var srcB2 = "";
+ var srcC2 = "[A]partial class C : I, J { void F() { } }";
+ var srcD2 = "[B]partial class C { void G() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")) }),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("G")) }),
+ });
+ }
+
+ ///
+ /// Moves partial classes to different files while moving around their attributes and base interfaces.
+ /// Currently we do not support splitting attribute lists.
+ ///
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteRefactor_AttributeListSplitting()
+ {
+ var srcA1 = "partial class C { void F() { } }";
+ var srcB1 = "[A,B]partial class C { void G() { } }";
+ var srcC1 = "";
+ var srcD1 = "";
+
+ var srcA2 = "";
+ var srcB2 = "";
+ var srcC2 = "[A]partial class C { void F() { } }";
+ var srcD2 = "[B]partial class C { void G() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(),
+ DocumentResults(diagnostics: new[] { Diagnostic(RudeEditKind.Update, "partial class C", FeaturesResources.class_) }),
+ DocumentResults(diagnostics: new[] { Diagnostic(RudeEditKind.Update, "partial class C", FeaturesResources.class_) }),
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteChangeMember()
+ {
+ var srcA1 = "partial class C { void F(int y = 1) { } }";
+ var srcB1 = "partial class C { void G(int x = 1) { } }";
+ var srcC1 = "";
+
+ var srcA2 = "";
+ var srcB2 = "partial class C { void G(int x = 2) { } }";
+ var srcC2 = "partial class C { void F(int y = 2) { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(diagnostics: new[] { Diagnostic(RudeEditKind.InitializerUpdate, "int x = 2", FeaturesResources.parameter) }),
+ DocumentResults(diagnostics: new[] { Diagnostic(RudeEditKind.InitializerUpdate, "int y = 2", FeaturesResources.parameter) }),
+ });
+ }
+
+ [Fact]
+ public void NestedPartialTypeInPartialType_InsertDeleteAndInsertVirtual()
+ {
+ var srcA1 = "partial interface I { partial class C { virtual void F1() {} } }";
+ var srcB1 = "partial interface I { partial class C { virtual void F2() {} } }";
+ var srcC1 = "partial interface I { partial class C { } }";
+ var srcD1 = "partial interface I { partial class C { } }";
+ var srcE1 = "partial interface I { }";
+ var srcF1 = "partial interface I { }";
+
+ var srcA2 = "partial interface I { partial class C { } }";
+ var srcB2 = "";
+ var srcC2 = "partial interface I { partial class C { virtual void F1() {} } }"; // move existing virtual into existing partial decl
+ var srcD2 = "partial interface I { partial class C { virtual void N1() {} } }"; // insert new virtual into existing partial decl
+ var srcE2 = "partial interface I { partial class C { virtual void F2() {} } }"; // move existing virtual into a new partial decl
+ 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) },
+ new[]
+ {
+ // A
+ DocumentResults(),
+
+ // B
+ DocumentResults(),
+
+ // C
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("C").GetMember("F1")) }),
+
+ // D
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.InsertVirtual, "virtual void N1()", FeaturesResources.method) }),
+
+ // E
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("I").GetMember("C").GetMember("F2")) }),
+
+ // F
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.InsertVirtual, "virtual void N2()", FeaturesResources.method) }),
+ });
+ }
+
+ #endregion
+
+ #region Namespaces
+
+ [Fact]
+ public void Namespace_Insert()
+ {
+ var src1 = @"";
+ var src2 = @"namespace C { }";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Insert [namespace C { }]@0");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "namespace C", FeaturesResources.namespace_));
+
+ }
+ [Fact]
+ public void Namespace_InsertNested()
+ {
+ var src1 = @"namespace C { }";
+ var src2 = @"namespace C { namespace D { } }";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Insert [namespace D { }]@14");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Insert, "namespace D", FeaturesResources.namespace_));
+ }
+
+ [Fact]
+ public void NamespaceDelete()
+ {
+ var src1 = @"namespace C { namespace D { } }";
+ var src2 = @"namespace C { }";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Delete [namespace D { }]@14");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "namespace C", FeaturesResources.namespace_));
+ }
+
+ [Fact]
+ public void NamespaceMove1()
+ {
+ var src1 = @"namespace C { namespace D { } }";
+ var src2 = @"namespace C { } namespace D { }";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Move [namespace D { }]@14 -> @16");
+
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.Move, "namespace D", FeaturesResources.namespace_));
+ }
+
+ [Fact]
+ public void NamespaceReorder1()
+ {
+ var src1 = @"namespace C { namespace D { } class T { } namespace E { } }";
+ var src2 = @"namespace C { namespace E { } class T { } namespace D { } }";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Reorder [class T { }]@30 -> @30",
+ "Reorder [namespace E { }]@42 -> @14");
+
+ edits.VerifyRudeDiagnostics();
+ }
+
+ [Fact]
+ public void NamespaceReorder2()
+ {
+ var src1 = @"namespace C { namespace D1 { } namespace D2 { } namespace D3 { } class T { } namespace E { } }";
+ var src2 = @"namespace C { namespace E { } class T { } namespace D1 { } namespace D2 { } namespace D3 { } }";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Reorder [class T { }]@65 -> @65",
+ "Reorder [namespace E { }]@77 -> @14");
+
+ edits.VerifyRudeDiagnostics();
+ }
+
+ #endregion
+
+ #region Members
+
+ [Fact]
+ public void MemberUpdate_Modifier_ReadOnly_Remove()
+ {
+ var src1 = @"
+using System;
+
+struct S
+{
+ // methods
+ public readonly int M() => 1;
+
+ // properties
+ public readonly int P => 1;
+ public readonly int Q { get; }
+ public int R { readonly get; readonly set; }
+
+ // events
+ public readonly event Action E { add {} remove {} }
+ public event Action F { readonly add {} readonly remove {} }
+}";
+ var src2 = @"
+using System;
+struct S
+{
+ // methods
+ public int M() => 1;
+
+ // properties
+ public int P => 1;
+ public int Q { get; }
+ public int R { get; set; }
+
+ // events
+ public event Action E { add {} remove {} }
+ public event Action F { add {} remove {} }
+}";
+ var edits = GetTopEdits(src1, src2);
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.ModifiersUpdate, "public int M()", FeaturesResources.method),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "public int P", FeaturesResources.property_),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "public int Q", FeaturesResources.auto_property),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "get", CSharpFeaturesResources.property_getter),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "set", CSharpFeaturesResources.property_setter),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "add", FeaturesResources.event_accessor),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "remove", FeaturesResources.event_accessor));
+ }
+
+ [Fact]
+ public void MemberUpdate_Modifier_ReadOnly_Add()
+ {
+ var src1 = @"
+using System;
+
+struct S
+{
+ // methods
+ public int M() => 1;
+
+ // properties
+ public int P => 1;
+ public int Q { get; }
+ public int R { get; set; }
+
+ // events
+ public event Action E { add {} remove {} }
+ public event Action F { add {} remove {} }
+}";
+ var src2 = @"
+using System;
+
+struct S
+{
+ // methods
+ public readonly int M() => 1;
+
+ // properties
+ public readonly int P => 1;
+ public readonly int Q { get; }
+ public int R { readonly get; readonly set; }
+
+ // events
+ public readonly event Action E { add {} remove {} }
+ public event Action F { readonly add {} readonly remove {} }
+}";
+ var edits = GetTopEdits(src1, src2);
+ edits.VerifyRudeDiagnostics(
+ Diagnostic(RudeEditKind.ModifiersUpdate, "public readonly int M()", FeaturesResources.method),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "public readonly int P", FeaturesResources.property_),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "public readonly int Q", FeaturesResources.auto_property),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "readonly get", CSharpFeaturesResources.property_getter),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "readonly set", CSharpFeaturesResources.property_setter),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "readonly add", FeaturesResources.event_accessor),
+ Diagnostic(RudeEditKind.ModifiersUpdate, "readonly remove", FeaturesResources.event_accessor));
+ }
+
+ [Fact]
+ public void PartialMember_DeleteInsert_SingleDocument()
+ {
+ var src1 = @"
+using System;
+
+partial class C
+{
+ void M() {}
+ int P1 { get; set; }
+ int P2 { get => 1; set {} }
+ int this[int i] { get => 1; set {} }
+ int this[byte i] { get => 1; set {} }
+ event Action E { add {} remove {} }
+ event Action EF;
+ int F1;
+ int F2;
+}
+
+partial class C
+{
+}
+";
+ var src2 = @"
+using System;
+
+partial class C
+{
+}
+
+partial class C
+{
+ void M() {}
+ int P1 { get; set; }
+ int P2 { get => 1; set {} }
+ int this[int i] { get => 1; set {} }
+ int this[byte i] { get => 1; set {} }
+ event Action E { add {} remove {} }
+ event Action EF;
+ int F1, F2;
+}
+";
+
+ var edits = GetTopEdits(src1, src2);
+
+ edits.VerifyEdits(
+ "Insert [void M() {}]@68",
+ "Insert [int P1 { get; set; }]@85",
+ "Insert [int P2 { get => 1; set {} }]@111",
+ "Insert [int this[int i] { get => 1; set {} }]@144",
+ "Insert [int this[byte i] { get => 1; set {} }]@186",
+ "Insert [event Action E { add {} remove {} }]@229",
+ "Insert [event Action EF;]@270",
+ "Insert [int F1, F2;]@292",
+ "Insert [()]@74",
+ "Insert [{ get; set; }]@92",
+ "Insert [{ get => 1; set {} }]@118",
+ "Insert [[int i]]@152",
+ "Insert [{ get => 1; set {} }]@160",
+ "Insert [[byte i]]@194",
+ "Insert [{ get => 1; set {} }]@203",
+ "Insert [{ add {} remove {} }]@244",
+ "Insert [Action EF]@276",
+ "Insert [int F1, F2]@292",
+ "Insert [get;]@94",
+ "Insert [set;]@99",
+ "Insert [get => 1;]@120",
+ "Insert [set {}]@130",
+ "Insert [int i]@153",
+ "Insert [get => 1;]@162",
+ "Insert [set {}]@172",
+ "Insert [byte i]@195",
+ "Insert [get => 1;]@205",
+ "Insert [set {}]@215",
+ "Insert [add {}]@246",
+ "Insert [remove {}]@253",
+ "Insert [EF]@283",
+ "Insert [F1]@296",
+ "Insert [F2]@300",
+ "Delete [void M() {}]@43",
+ "Delete [()]@49",
+ "Delete [int P1 { get; set; }]@60",
+ "Delete [{ get; set; }]@67",
+ "Delete [get;]@69",
+ "Delete [set;]@74",
+ "Delete [int P2 { get => 1; set {} }]@86",
+ "Delete [{ get => 1; set {} }]@93",
+ "Delete [get => 1;]@95",
+ "Delete [set {}]@105",
+ "Delete [int this[int i] { get => 1; set {} }]@119",
+ "Delete [[int i]]@127",
+ "Delete [int i]@128",
+ "Delete [{ get => 1; set {} }]@135",
+ "Delete [get => 1;]@137",
+ "Delete [set {}]@147",
+ "Delete [int this[byte i] { get => 1; set {} }]@161",
+ "Delete [[byte i]]@169",
+ "Delete [byte i]@170",
+ "Delete [{ get => 1; set {} }]@178",
+ "Delete [get => 1;]@180",
+ "Delete [set {}]@190",
+ "Delete [event Action E { add {} remove {} }]@204",
+ "Delete [{ add {} remove {} }]@219",
+ "Delete [add {}]@221",
+ "Delete [remove {}]@228",
+ "Delete [event Action EF;]@245",
+ "Delete [Action EF]@251",
+ "Delete [EF]@258",
+ "Delete [int F1;]@267",
+ "Delete [int F1]@267",
+ "Delete [F1]@271",
+ "Delete [int F2;]@280",
+ "Delete [int F2]@280",
+ "Delete [F2]@284");
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { edits },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("M"), preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P2").GetMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P2").SetMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMembers("this[]").Cast().Single(m => m.GetParameters().Single().Type.Name == "Int32").GetMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMembers("this[]").Cast().Single(m => m.GetParameters().Single().Type.Name == "Int32").SetMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMembers("this[]").Cast().Single(m => m.GetParameters().Single().Type.Name == "Byte").GetMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMembers("this[]").Cast().Single(m => m.GetParameters().Single().Type.Name == "Byte").SetMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("E").AddMethod, preserveLocalVariables: false),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("E").RemoveMethod, preserveLocalVariables: false),
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialMember_InsertDelete_MultipleDocuments()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "partial class C { void F() {} }";
+ var srcA2 = "partial class C { void F() {} }";
+ var srcB2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F"), preserveLocalVariables: false)
+ }),
+
+ DocumentResults()
+ });
+ }
+
+ [Fact]
+ public void PartialMember_DeleteInsert_MultipleDocuments()
+ {
+ var srcA1 = "partial class C { void F() {} }";
+ var srcB1 = "partial class C { }";
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { void F() {} }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F"), preserveLocalVariables: false)
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialMember_DeleteInsert_GenericMethod()
+ {
+ var srcA1 = "partial class C { void F() {} }";
+ var srcB1 = "partial class C { }";
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { void F() {} }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(diagnostics: new[]
+ {
+ // TODO: better message
+ Diagnostic(RudeEditKind.GenericMethodTriviaUpdate, "void F()", FeaturesResources.method)
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialMember_DeleteInsert_GenericType()
+ {
+ var srcA1 = "partial class C { void F() {} }";
+ var srcB1 = "partial class C { }";
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { void F() {} }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(diagnostics: new[]
+ {
+ // TODO: better message
+ Diagnostic(RudeEditKind.GenericTypeTriviaUpdate, "void F()", FeaturesResources.method)
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialMember_DeleteInsert_Destructor()
+ {
+ var srcA1 = "partial class C { ~C() {} }";
+ var srcB1 = "partial class C { }";
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { ~C() {} }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("Finalize"), preserveLocalVariables: false),
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialNestedType_InsertDeleteAndChange()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "partial class C { class D { void M() {} } interface I { } }";
+
+ var srcA2 = "partial class C { class D : I { void M() {} } interface I { } }";
+ var srcB2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.BaseTypeOrInterfaceUpdate, "class D", FeaturesResources.class_),
+ }),
+
+ DocumentResults()
+ });
+ }
- [Fact]
- public void NamespaceMove1()
+ [Fact, WorkItem(51011, "https://github.com/dotnet/roslyn/issues/51011")]
+ public void PartialMember_RenameInsertDelete()
{
- var src1 = @"namespace C { namespace D { } }";
- var src2 = @"namespace C { } namespace D { }";
+ // The syntactic analysis for A and B produce rename edits since it doesn't see that the member was in fact moved.
+ // TODO: Currently, we don't even pass rename edits to semantic analysis where we could handle them as updates.
- var edits = GetTopEdits(src1, src2);
+ var srcA1 = "partial class C { void F1() {} }";
+ var srcB1 = "partial class C { void F2() {} }";
+ var srcA2 = "partial class C { void F2() {} }";
+ var srcB2 = "partial class C { void F1() {} }";
- edits.VerifyEdits(
- "Move [namespace D { }]@14 -> @16");
+ // current outcome:
+ GetTopEdits(srcA1, srcA2).VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Renamed, "void F2()", FeaturesResources.method));
+ GetTopEdits(srcB1, srcB2).VerifyRudeDiagnostics(Diagnostic(RudeEditKind.Renamed, "void F1()", FeaturesResources.method));
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Move, "namespace D", FeaturesResources.namespace_));
+ // correct outcome:
+ //EditAndContinueValidation.VerifySemantics(
+ // new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ // new[]
+ // {
+ // DocumentResults(semanticEdits: new[]
+ // {
+ // SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F2")),
+ // }),
+
+ // DocumentResults(
+ // semanticEdits: new[]
+ // {
+ // SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F1")),
+ // })
+ // });
}
[Fact]
- public void NamespaceReorder1()
+ public void PartialMember_DeleteInsert_UpdateMethodBodyError()
{
- var src1 = @"namespace C { namespace D { } class T { } namespace E { } }";
- var src2 = @"namespace C { namespace E { } class T { } namespace D { } }";
+ var srcA1 = @"
+using System.Collections.Generic;
- var edits = GetTopEdits(src1, src2);
+partial class C
+{
+ IEnumerable F() { yield return 1; }
+}
+";
+ var srcB1 = @"
+using System.Collections.Generic;
- edits.VerifyEdits(
- "Reorder [class T { }]@30 -> @30",
- "Reorder [namespace E { }]@42 -> @14");
+partial class C
+{
+}
+";
- edits.VerifyRudeDiagnostics();
+ var srcA2 = @"
+using System.Collections.Generic;
+
+partial class C
+{
+}
+";
+ var srcB2 = @"
+using System.Collections.Generic;
+
+partial class C
+{
+ IEnumerable F() { yield return 1; yield return 2; }
+}
+";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(diagnostics: new[]
+ {
+ Diagnostic(RudeEditKind.Insert, "yield return 2;", CSharpFeaturesResources.yield_return_statement)
+ })
+ });
}
[Fact]
- public void NamespaceReorder2()
+ public void PartialMember_DeleteInsert_UpdatePropertyAccessors()
{
- var src1 = @"namespace C { namespace D1 { } namespace D2 { } namespace D3 { } class T { } namespace E { } }";
- var src2 = @"namespace C { namespace E { } class T { } namespace D1 { } namespace D2 { } namespace D3 { } }";
-
- var edits = GetTopEdits(src1, src2);
+ var srcA1 = "partial class C { int P { get => 1; set { Console.WriteLine(1); } } }";
+ var srcB1 = "partial class C { }";
- edits.VerifyEdits(
- "Reorder [class T { }]@65 -> @65",
- "Reorder [namespace E { }]@77 -> @14");
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { int P { get => 2; set { Console.WriteLine(2); } } }";
- edits.VerifyRudeDiagnostics();
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").SetMethod)
+ })
+ });
}
- #endregion
-
- #region Members
-
[Fact]
- public void MemberUpdate_Modifier_ReadOnly_Remove()
+ public void PartialMember_DeleteInsert_UpdateAutoProperty()
{
- var src1 = @"
-using System;
+ var srcA1 = "partial class C { int P => 1; }";
+ var srcB1 = "partial class C { }";
-struct S
-{
- // methods
- public readonly int M() => 1;
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { int P => 2; }";
- // properties
- public readonly int P => 1;
- public readonly int Q { get; }
- public int R { readonly get; readonly set; }
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("P").GetMethod)
+ })
+ });
+ }
- // events
- public readonly event Action E { add {} remove {} }
- public event Action F { readonly add {} readonly remove {} }
-}";
- var src2 = @"
-using System;
-struct S
-{
- // methods
- public int M() => 1;
+ [Fact]
+ public void PartialMember_DeleteInsert_AddFieldInitializer()
+ {
+ var srcA1 = "partial class C { int f; }";
+ var srcB1 = "partial class C { }";
- // properties
- public int P => 1;
- public int Q { get; }
- public int R { get; set; }
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { int f = 1; }";
- // events
- public event Action E { add {} remove {} }
- public event Action F { add {} remove {} }
-}";
- var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.ModifiersUpdate, "public int M()", FeaturesResources.method),
- Diagnostic(RudeEditKind.ModifiersUpdate, "public int P", FeaturesResources.property_),
- Diagnostic(RudeEditKind.ModifiersUpdate, "public int Q", FeaturesResources.auto_property),
- Diagnostic(RudeEditKind.ModifiersUpdate, "get", CSharpFeaturesResources.property_getter),
- Diagnostic(RudeEditKind.ModifiersUpdate, "set", CSharpFeaturesResources.property_setter),
- Diagnostic(RudeEditKind.ModifiersUpdate, "add", FeaturesResources.event_accessor),
- Diagnostic(RudeEditKind.ModifiersUpdate, "remove", FeaturesResources.event_accessor));
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ })
+ });
}
[Fact]
- public void MemberUpdate_Modifier_ReadOnly_Add()
+ public void PartialMember_DeleteInsert_RemoveFieldInitializer()
{
- var src1 = @"
-using System;
-
-struct S
-{
- // methods
- public int M() => 1;
+ var srcA1 = "partial class C { int f = 1; }";
+ var srcB1 = "partial class C { }";
- // properties
- public int P => 1;
- public int Q { get; }
- public int R { get; set; }
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { int f; }";
- // events
- public event Action E { add {} remove {} }
- public event Action F { add {} remove {} }
-}";
- var src2 = @"
-using System;
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ })
+ });
+ }
-struct S
-{
- // methods
- public readonly int M() => 1;
+ [Fact]
+ public void PartialMember_DeleteInsert_ConstructorWithInitializers()
+ {
+ var srcA1 = "partial class C { int f = 1; C(int x) { f = x; } }";
+ var srcB1 = "partial class C { }";
- // properties
- public readonly int P => 1;
- public readonly int Q { get; }
- public int R { readonly get; readonly set; }
+ var srcA2 = "partial class C { int f = 1; }";
+ var srcB2 = "partial class C { C(int x) { f = x + 1; } }";
- // events
- public readonly event Action E { add {} remove {} }
- public event Action F { readonly add {} readonly remove {} }
-}";
- var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.ModifiersUpdate, "public readonly int M()", FeaturesResources.method),
- Diagnostic(RudeEditKind.ModifiersUpdate, "public readonly int P", FeaturesResources.property_),
- Diagnostic(RudeEditKind.ModifiersUpdate, "public readonly int Q", FeaturesResources.auto_property),
- Diagnostic(RudeEditKind.ModifiersUpdate, "readonly get", CSharpFeaturesResources.property_getter),
- Diagnostic(RudeEditKind.ModifiersUpdate, "readonly set", CSharpFeaturesResources.property_setter),
- Diagnostic(RudeEditKind.ModifiersUpdate, "readonly add", FeaturesResources.event_accessor),
- Diagnostic(RudeEditKind.ModifiersUpdate, "readonly remove", FeaturesResources.event_accessor));
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ })
+ });
}
#endregion
@@ -2380,20 +3747,11 @@ public void Method_Delete()
class C
{
void goo() { }
-
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}
";
var src2 = @"
class C
{
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}";
var edits = GetTopEdits(src1, src2);
@@ -2401,8 +3759,8 @@ static void Main(string[] args)
"Delete [void goo() { }]@18",
"Delete [()]@26");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.method));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.method, "goo()")));
}
[Fact]
@@ -2412,20 +3770,11 @@ public void MethodWithExpressionBody_Delete()
class C
{
int goo() => 1;
-
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}
";
var src2 = @"
class C
{
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}";
var edits = GetTopEdits(src1, src2);
@@ -2433,66 +3782,24 @@ static void Main(string[] args)
"Delete [int goo() => 1;]@18",
"Delete [()]@25");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.method));
- }
-
- [Fact]
- public void MethodDelete_WithParameters()
- {
- var src1 = @"
-class C
-{
- void goo(int a) { }
-
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
-}
-";
- var src2 = @"
-class C
-{
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
-}";
- var edits = GetTopEdits(src1, src2);
-
- edits.VerifyEdits(
- "Delete [void goo(int a) { }]@18",
- "Delete [(int a)]@26",
- "Delete [int a]@27");
-
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.method));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.method, "goo()")));
}
[WorkItem(754853, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/754853")]
[Fact]
- public void MethodDelete_WithAttribute()
+ public void MethodDelete_WithParameterAndAttribute()
{
var src1 = @"
class C
{
[Obsolete]
void goo(int a) { }
-
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}
";
var src2 = @"
class C
{
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}";
var edits = GetTopEdits(src1, src2);
@@ -2504,8 +3811,8 @@ void goo(int a) { }]@18",
"Delete [(int a)]@42",
"Delete [int a]@43");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.method));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.method, "goo(int)")));
}
[WorkItem(754853, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/754853")]
@@ -2520,11 +3827,6 @@ class C
{
[DllImport(""msvcrt.dll"")]
public static extern int puts(string c);
-
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}
";
var src2 = @"
@@ -2533,10 +3835,6 @@ static void Main(string[] args)
class C
{
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}";
var edits = GetTopEdits(src1, src2);
@@ -2549,8 +3847,8 @@ static void Main(string[] args)
"Delete [(string c)]@134",
"Delete [string c]@135");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.method));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.method, "puts(string)")));
}
[Fact]
@@ -2675,7 +3973,7 @@ public virtual void F() {}
";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertVirtual, "public virtual void F()", FeaturesResources.method));
}
@@ -2694,7 +3992,7 @@ abstract class C
";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertVirtual, "public abstract void F()", FeaturesResources.method));
}
@@ -2713,13 +4011,13 @@ public override void F() { }
";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertVirtual, "public override void F()", FeaturesResources.method));
}
[WorkItem(755784, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/755784"), WorkItem(835827, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/835827")]
[Fact]
- public void PrivateMethodInsert_PInvoke1()
+ public void ExternMethodInsert()
{
var src1 = @"
using System;
@@ -2727,10 +4025,6 @@ public void PrivateMethodInsert_PInvoke1()
class C
{
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}";
var src2 = @"
using System;
@@ -2740,11 +4034,6 @@ class C
{
[DllImport(""msvcrt.dll"")]
private static extern int puts(string c);
-
- static void Main(string[] args)
- {
- Console.ReadLine();
- }
}
";
var edits = GetTopEdits(src1, src2);
@@ -2758,10 +4047,51 @@ static void Main(string[] args)
"Insert [string c]@136");
// CLR doesn't support methods without a body
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertExtern, "private static extern int puts(string c)", FeaturesResources.method));
}
+ [WorkItem(755784, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/755784"), WorkItem(835827, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/835827")]
+ [Fact]
+ public void ExternMethodDeleteInsert()
+ {
+ var srcA1 = @"
+using System;
+using System.Runtime.InteropServices;
+
+class C
+{
+ [DllImport(""msvcrt.dll"")]
+ private static extern int puts(string c);
+}";
+ var srcA2 = @"
+using System;
+using System.Runtime.InteropServices;
+";
+
+ var srcB1 = @"
+using System;
+using System.Runtime.InteropServices;
+";
+ var srcB2 = @"
+using System;
+using System.Runtime.InteropServices;
+
+class C
+{
+ [DllImport(""msvcrt.dll"")]
+ private static extern int puts(string c);
+}
+";
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults()
+ });
+ }
+
[Fact]
public void MethodReorder1()
{
@@ -3983,10 +5313,162 @@ public class SubClass : BaseClass, IConflict
"Insert [string IConflict.Get() => String.Empty;]@325",
"Insert [()]@345");
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertMethodWithExplicitInterfaceSpecifier, "string IConflict.Get()", FeaturesResources.method));
}
+ [Fact]
+ public void PartialMethod_DeleteInsert_DefinitionPart()
+ {
+ var srcA1 = "partial class C { partial void F(); }";
+ var srcB1 = "partial class C { partial void F() { } }";
+ var srcC1 = "partial class C { }";
+
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { partial void F() { } }";
+ var srcC2 = "partial class C { partial void F(); }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(),
+ DocumentResults(),
+ });
+ }
+
+ [Fact]
+ public void PartialMethod_DeleteInsert_ImplementationPart()
+ {
+ var srcA1 = "partial class C { partial void F(); }";
+ var srcB1 = "partial class C { partial void F() { } }";
+ var srcC1 = "partial class C { }";
+
+ var srcA2 = "partial class C { partial void F(); }";
+ var srcB2 = "partial class C { }";
+ var srcC2 = "partial class C { partial void F() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(),
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart) }),
+ });
+ }
+
+ [Fact, WorkItem(51011, "https://github.com/dotnet/roslyn/issues/51011")]
+ public void PartialMethod_Swap_ImplementationAndDefinitionParts()
+ {
+ var srcA1 = "partial class C { partial void F(); }";
+ var srcB1 = "partial class C { partial void F() { } }";
+
+ var srcA2 = "partial class C { partial void F() { } }";
+ var srcB2 = "partial class C { partial void F(); }";
+
+ // current:
+ GetTopEdits(srcA1, srcA2).VerifyRudeDiagnostics(Diagnostic(RudeEditKind.MethodBodyAdd, "partial void F()", FeaturesResources.method));
+ GetTopEdits(srcB1, srcB2).VerifyRudeDiagnostics(Diagnostic(RudeEditKind.MethodBodyDelete, "partial void F()", FeaturesResources.method));
+
+ // correct: TODO
+ //EditAndContinueValidation.VerifySemantics(
+ // new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ // new[]
+ // {
+ // DocumentResults(),
+ // DocumentResults(
+ // semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F")) }),
+ // });
+ }
+
+ [Fact]
+ public void PartialMethod_DeleteImplementation()
+ {
+ var srcA1 = "partial class C { partial void F(); }";
+ var srcB1 = "partial class C { partial void F() { } }";
+
+ var srcA2 = "partial class C { partial void F(); }";
+ var srcB2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Delete, "partial class C", DeletedSymbolDisplay(FeaturesResources.method, "F()")) })
+ });
+ }
+
+ [Fact]
+ public void PartialMethod_DeleteBoth()
+ {
+ var srcA1 = "partial class C { partial void F(); }";
+ var srcB1 = "partial class C { partial void F() { } }";
+
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.Delete, "partial class C", DeletedSymbolDisplay(FeaturesResources.method, "F()")) })
+ });
+ }
+
+ [Fact]
+ public void PartialMethod_DeleteInsertBoth()
+ {
+ var srcA1 = "partial class C { partial void F(); }";
+ var srcB1 = "partial class C { partial void F() { } }";
+ var srcC1 = "partial class C { }";
+ var srcD1 = "partial class C { }";
+
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { }";
+ var srcC2 = "partial class C { partial void F(); }";
+ var srcD2 = "partial class C { partial void F() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2), GetTopEdits(srcC1, srcC2), GetTopEdits(srcD1, srcD2) },
+ new[]
+ {
+ DocumentResults(),
+ DocumentResults(),
+ DocumentResults(),
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F").PartialImplementationPart) })
+ });
+ }
+
+ [Fact]
+ public void PartialMethod_Insert()
+ {
+ var srcA1 = "partial class C { }";
+ var srcB1 = "partial class C { }";
+
+ var srcA2 = "partial class C { partial void F(); }";
+ var srcB2 = "partial class C { partial void F() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").GetMember("F").PartialImplementationPart) }),
+ });
+ }
+
#endregion
#region Operators
@@ -4014,7 +5496,7 @@ public static implicit operator bool (C c)
}";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertOperator, "public static implicit operator bool (C c)", CSharpFeaturesResources.conversion_operator),
Diagnostic(RudeEditKind.InsertOperator, "public static C operator +(C c, C d)", FeaturesResources.operator_));
}
@@ -4042,9 +5524,46 @@ class C
}";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", CSharpFeaturesResources.conversion_operator),
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.operator_));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(CSharpFeaturesResources.conversion_operator, "implicit operator bool(C)")),
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.operator_, "operator +(C, C)")));
+ }
+
+ [Fact]
+ public void OperatorInsertDelete()
+ {
+ var srcA1 = @"
+partial class C
+{
+ public static implicit operator bool (C c) => false;
+}
+";
+ var srcB1 = @"
+partial class C
+{
+ public static C operator +(C c, C d) => c;
+}
+";
+
+ var srcA2 = srcB1;
+ var srcB2 = srcA1;
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("op_Addition"))
+ }),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("op_Implicit"))
+ }),
+ });
}
[Fact]
@@ -4204,7 +5723,7 @@ public void Operator_ReadOnlyRef_Parameter_InsertWhole()
"Insert [(in Test b)]@42",
"Insert [in Test b]@43");
- edits.VerifyRudeDiagnostics(
+ edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.InsertOperator, "public static bool operator !(in Test b)", FeaturesResources.operator_));
}
@@ -4321,21 +5840,11 @@ public void ConstructorUpdate_AddParameter()
class C
{
public C(int a) { }
-
- static void Main(string[] args)
- {
- C c = new C(5);
- }
}";
var src2 = @"
class C
{
public C(int a, int b) { }
-
- static void Main(string[] args)
- {
- C c = new C(5);
- }
}";
var edits = GetTopEdits(src1, src2);
@@ -4350,108 +5859,35 @@ static void Main(string[] args)
[Fact]
public void DestructorDelete()
{
- var src1 = @"
-class C
-{
- static void Main(string[] args)
- {
- B b = new B();
- b = null;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
-}
-class B
-{
- ~B()
- {
- Console.WriteLine(""B's destructor"");
- }
-}";
- var src2 = @"
-class C
-{
- static void Main(string[] args)
- {
- B b = new B();
- b = null;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
-}
-class B
-{
+ var src1 = @"class B { ~B() { } }";
+ var src2 = @"class B { }";
-}";
-
- var expectedEdit1 = @"Delete [~B()
- {
- Console.WriteLine(""B's destructor"");
- }]@190";
+ var expectedEdit1 = @"Delete [~B() { }]@10";
var edits = GetTopEdits(src1, src2);
edits.VerifyEdits(expectedEdit1);
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class B", CSharpFeaturesResources.destructor));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.Delete, "class B", DeletedSymbolDisplay(CSharpFeaturesResources.destructor, "~B()")));
}
[Fact]
public void DestructorDelete_InsertConstructor()
{
- var src1 = @"
-class C
-{
- static void Main(string[] args)
- {
- B b = new B();
- b = null;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
-}
-class B
-{
- ~B()
- {
- Console.WriteLine(""B's destructor"");
- }
-}";
- var src2 = @"
-class C
-{
- static void Main(string[] args)
- {
- B b = new B();
- b = null;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
-}
-class B
-{
- B()
- {
- Console.WriteLine(""B's destructor"");
- }
-}";
- var expectedEdit1 = @"Insert [B()
- {
- Console.WriteLine(""B's destructor"");
- }]@190";
-
- var expectedEdit2 = @"Delete [~B()
- {
- Console.WriteLine(""B's destructor"");
- }]@190";
+ var src1 = @"class B { ~B() { } }";
+ var src2 = @"class B { B() { } }";
var edits = GetTopEdits(src1, src2);
- edits.VerifyEdits(expectedEdit1, "Insert [()]@191", expectedEdit2);
+ edits.VerifyEdits(
+ "Insert [B() { }]@10",
+ "Insert [()]@11",
+ "Delete [~B() { }]@10");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class B", CSharpFeaturesResources.destructor));
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.ChangingVisibility, "B()", FeaturesResources.constructor),
+ Diagnostic(RudeEditKind.Delete, "class B", DeletedSymbolDisplay(CSharpFeaturesResources.destructor, "~B()")));
}
[Fact]
@@ -4463,92 +5899,71 @@ public void ConstructorUpdate_AnonymousTypeInFieldInitializer()
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics();
- }
-
- [Fact]
- public void StaticCtorDelete()
- {
- var src1 = "class C { static C() { } }";
- var src2 = "class C { }";
-
- var edits = GetTopEdits(src1, src2);
-
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
- }
-
- [Fact]
- public void InstanceCtorDelete_Public()
- {
- var src1 = "class C { public C() { } }";
- var src2 = "class C { }";
-
- var edits = GetTopEdits(src1, src2);
-
- edits.VerifySemantics(
- ActiveStatementsDescription.Empty,
- new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single()) });
- }
-
- [Fact]
- public void InstanceCtorDelete_Private1()
- {
- var src1 = "class C { C() { } }";
- var src2 = "class C { }";
-
- var edits = GetTopEdits(src1, src2);
-
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ edits.VerifyRudeDiagnostics();
}
[Fact]
- public void InstanceCtorDelete_Private2()
+ public void StaticCtorDelete()
{
- var src1 = "class C { private C() { } }";
+ var src1 = "class C { static C() { } }";
var src2 = "class C { }";
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ Diagnostic(RudeEditKind.Delete, "class C", DeletedSymbolDisplay(FeaturesResources.static_constructor, "C()")));
}
[Fact]
- public void InstanceCtorDelete_Protected()
+ public void InstanceCtorDelete_Public()
{
- var src1 = "class C { protected C() { } }";
+ var src1 = "class C { public C() { } }";
var src2 = "class C { }";
var edits = GetTopEdits(src1, src2);
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ edits.VerifySemantics(
+ ActiveStatementsDescription.Empty,
+ new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) });
}
- [Fact]
- public void InstanceCtorDelete_Internal()
- {
- var src1 = "class C { internal C() { } }";
+ [Theory]
+ [InlineData("")]
+ [InlineData("private")]
+ [InlineData("protected")]
+ [InlineData("internal")]
+ [InlineData("private protected")]
+ [InlineData("protected internal")]
+ public void InstanceCtorDelete_NonPublic(string visibility)
+ {
+ var src1 = "class C { " + visibility + " C() { } }";
var src2 = "class C { }";
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ Diagnostic(RudeEditKind.ChangingVisibility, "class C", DeletedSymbolDisplay(FeaturesResources.constructor, "C()")));
}
[Fact]
- public void InstanceCtorDelete_ProtectedInternal()
+ public void InstanceCtorDelete_Public_PartialWithInitializerUpdate()
{
- var src1 = "class C { protected internal C() { } }";
- var src2 = "class C { }";
+ var srcA1 = "partial class C { public C() { } }";
+ var srcB1 = "partial class C { int x = 1; }";
- var edits = GetTopEdits(src1, src2);
+ var srcA2 = "partial class C { }";
+ var srcB2 = "partial class C { int x = 2; }";
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true) }),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true) })
+ });
}
[Fact]
@@ -4588,9 +6003,13 @@ public void InstanceCtorInsert_Partial_Public_Implicit()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ // no change in document A
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) }),
});
}
@@ -4621,9 +6040,16 @@ public void InstanceCtorInsert_Partial_Public_NoImplicit()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters.IsEmpty))
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").InstanceConstructors.Single(c => c.Parameters.IsEmpty))
+ }),
+
+ // no change in document B
+ DocumentResults(),
});
}
@@ -4636,7 +6062,7 @@ public void InstanceCtorInsert_Private_Implicit1()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "private C()"));
+ Diagnostic(RudeEditKind.ChangingVisibility, "private C()", FeaturesResources.constructor));
}
[Fact]
@@ -4648,7 +6074,7 @@ public void InstanceCtorInsert_Private_Implicit2()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "C()"));
+ Diagnostic(RudeEditKind.ChangingVisibility, "C()", FeaturesResources.constructor));
}
[Fact]
@@ -4660,7 +6086,7 @@ public void InstanceCtorInsert_Protected_PublicImplicit()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "protected C()"));
+ Diagnostic(RudeEditKind.ChangingVisibility, "protected C()", FeaturesResources.constructor));
}
[Fact]
@@ -4672,7 +6098,7 @@ public void InstanceCtorInsert_Internal_PublicImplicit()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "internal C()"));
+ Diagnostic(RudeEditKind.ChangingVisibility, "internal C()", FeaturesResources.constructor));
}
[Fact]
@@ -4684,7 +6110,7 @@ public void InstanceCtorInsert_Internal_ProtectedImplicit()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "internal C()"));
+ Diagnostic(RudeEditKind.ChangingVisibility, "internal C()", FeaturesResources.constructor));
}
[Fact]
@@ -4764,11 +6190,16 @@ public void StaticCtor_Partial_DeleteInsert()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- targetFrameworks: null,
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), 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(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)
+ }),
});
}
@@ -4783,10 +6214,16 @@ public void InstanceCtor_Partial_DeletePrivateInsertPrivate()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), 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(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ }),
});
}
@@ -4801,10 +6238,16 @@ public void InstanceCtor_Partial_DeletePublicInsertPublic()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), 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(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ }),
});
}
@@ -4819,10 +6262,14 @@ public void InstanceCtor_Partial_DeletePrivateInsertPublic()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedDiagnostics: new[]
+ new[]
{
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "public C()")
+ // delete of the constructor in partial part will be reported as rude edit in the other document where it was inserted back with changed visibility
+ DocumentResults(
+ semanticEdits: NoSemanticEdits),
+
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.ModifiersUpdate, "public C()", FeaturesResources.constructor) }),
});
}
@@ -4837,10 +6284,16 @@ public void StaticCtor_Partial_InsertDelete()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true)
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), 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(),
});
}
@@ -4855,10 +6308,16 @@ public void InstanceCtor_Partial_InsertPublicDeletePublic()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), 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(),
});
}
@@ -4873,10 +6332,16 @@ public void InstanceCtor_Partial_InsertPrivateDeletePrivate()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), 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(),
});
}
@@ -4891,9 +6356,16 @@ public void InstanceCtor_Partial_DeleteInternalInsertInternal()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), 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(),
});
}
@@ -4908,9 +6380,16 @@ public void InstanceCtor_Partial_InsertInternalDeleteInternal_WithBody()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- expectedSemanticEdits: new[]
+ new[]
{
- SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true)
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), 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(),
});
}
@@ -4925,10 +6404,13 @@ public void InstanceCtor_Partial_InsertPublicDeletePrivate()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedDiagnostics: new[]
+ new[]
{
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "public C()")
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.ModifiersUpdate, "public C()", FeaturesResources.constructor) }),
+
+ // delete of the constructor in partial part will be reported as rude in the the other document where it was inserted with changed visibility
+ DocumentResults(),
});
}
@@ -4943,10 +6425,12 @@ public void InstanceCtor_Partial_InsertInternalDeletePrivate()
EditAndContinueValidation.VerifySemantics(
new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
- activeStatements: ActiveStatementsDescription.Empty,
- expectedDiagnostics: new[]
+ new[]
{
- Diagnostic(RudeEditKind.ChangingConstructorVisibility, "internal C()")
+ DocumentResults(
+ diagnostics: new[] { Diagnostic(RudeEditKind.ModifiersUpdate, "internal C()", FeaturesResources.constructor) }),
+
+ DocumentResults(),
});
}
@@ -5105,7 +6589,7 @@ public C()
new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) });
}
- [Fact]
+ [Fact, WorkItem(2504, "https://github.com/dotnet/roslyn/issues/2504")]
public void InstanceCtor_Partial_Insert_Parameterless_LambdaInInitializer1()
{
var src1 = @"
@@ -5144,11 +6628,16 @@ partial class C
}
";
var edits = GetTopEdits(src1, src2);
- var syntaxMap = GetSyntaxMap(src1, src2);
- edits.VerifySemantics(
- ActiveStatementsDescription.Empty,
- new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) });
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.InsertConstructorToTypeWithInitializersWithLambdas, "public C()"));
+
+ // TODO:
+ //var syntaxMap = GetSyntaxMap(src1, src2);
+
+ //edits.VerifySemantics(
+ // ActiveStatementsDescription.Empty,
+ // new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) });
}
[Fact, WorkItem(2504, "https://github.com/dotnet/roslyn/issues/2504")]
@@ -5201,6 +6690,123 @@ partial class C
// new[] { SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").Constructors.Single(), syntaxMap[0]) });
}
+ [Fact]
+ public void PartialTypes_ConstructorWithInitializerUpdates()
+ {
+ var srcA1 = @"
+using System;
+
+partial class C
+{
+ C(int arg) => Console.WriteLine(0);
+ C(bool arg) => Console.WriteLine(1);
+}
+";
+ var srcB1 = @"
+using System;
+
+partial class C
+{
+ int a = 1;
+
+ C(uint arg) => Console.WriteLine(2);
+}
+";
+
+ var srcA2 = @"
+using System;
+
+partial class C
+{
+ C(int arg) => Console.WriteLine(0);
+ C(bool arg) => Console.WriteLine(1);
+}
+";
+ var srcB2 = @"
+using System;
+
+partial class C
+{
+ int a = 2; // updated field initializer
+
+ C(uint arg) => Console.WriteLine(2);
+ C(byte arg) => Console.WriteLine(3); // new ctor
+}
+";
+ var syntaxMapB = GetSyntaxMap(srcB1, srcB2)[0];
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ // No changes in document A
+ DocumentResults(),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Int32"), syntaxMap: syntaxMapB),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Boolean"), syntaxMap: syntaxMapB),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "UInt32"), syntaxMap: syntaxMapB),
+ SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Byte"), syntaxMap: null),
+ })
+ });
+ }
+
+ [Fact]
+ public void PartialTypes_ConstructorWithInitializerUpdates_SemanticErrors()
+ {
+ var srcA1 = @"
+using System;
+
+partial class C
+{
+ C(int arg) => Console.WriteLine(0);
+ C(int arg) => Console.WriteLine(1);
+}
+";
+ var srcB1 = @"
+using System;
+
+partial class C
+{
+ int a = 1;
+}
+";
+
+ var srcA2 = @"
+using System;
+
+partial class C
+{
+ C(int arg) => Console.WriteLine(0);
+ C(int arg) => Console.WriteLine(1);
+}
+";
+ var srcB2 = @"
+using System;
+
+partial class C
+{
+ int a = 2;
+
+ C(int arg) => Console.WriteLine(2);
+}
+";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ // No changes in document A
+ DocumentResults(),
+
+ // The actual edits do not matter since there are semantic errors in the compilation.
+ // We just should not crash.
+ DocumentResults(diagnostics: Array.Empty())
+ });
+ }
+
[WorkItem(2068, "https://github.com/dotnet/roslyn/issues/2068")]
[Fact]
public void Insert_ExternConstruct()
@@ -5214,11 +6820,11 @@ public void Insert_ExternConstruct()
"Insert [public extern C();]@10",
"Insert [()]@25");
- edits.VerifyRudeDiagnostics(
- Diagnostic(RudeEditKind.InsertExtern, "public extern C()", FeaturesResources.constructor));
+ // The compiler generates an empty constructor.
+ edits.VerifySemanticDiagnostics();
}
- [Fact(Skip = "https://github.com/dotnet/roslyn/pull/18940")]
+ [Fact]
public void ParameterlessConstructor_SemanticError_Delete1()
{
var src1 = @"
@@ -5234,19 +6840,9 @@ class C
";
var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics();
- }
-
- [Fact(Skip = "https://github.com/dotnet/roslyn/pull/18940")]
- public void ParameterlessConstructor_SemanticError_Delete_OutsideOfClass1()
- {
- var src1 = @"
-C() {}
-";
- var src2 = @"
-";
- var edits = GetTopEdits(src1, src2);
- edits.VerifyRudeDiagnostics();
+ // The compiler interprets D() as a constructor declaration.
+ edits.VerifySemanticDiagnostics(
+ Diagnostic(RudeEditKind.ChangingVisibility, "class C", DeletedSymbolDisplay(FeaturesResources.constructor, "C()")));
}
[Fact]
@@ -5288,6 +6884,56 @@ partial void C(int x)
});
}
+ [Fact]
+ public void PartialDeclaration_Delete()
+ {
+ var srcA1 = "partial class C { public C() { } void F() { } }";
+ var srcB1 = "partial class C { int x = 1; }";
+
+ var srcA2 = "";
+ var srcB2 = "partial class C { int x = 2; void F() { } }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true) }),
+
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F"), partialType: "C"),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true)
+ }),
+ });
+ }
+
+ [Fact]
+ public void PartialDeclaration_Insert()
+ {
+ var srcA1 = "";
+ var srcB1 = "partial class C { int x = 1; void F() { } }";
+
+ var srcA2 = "partial class C { public C() { } void F() { } }";
+ var srcB2 = "partial class C { int x = 2; }";
+
+ EditAndContinueValidation.VerifySemantics(
+ new[] { GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2) },
+ new[]
+ {
+ DocumentResults(
+ semanticEdits: new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").GetMember("F"), partialType: "C"),
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true)
+ }),
+
+ DocumentResults(
+ semanticEdits: new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), partialType: "C", preserveLocalVariables: true) }),
+ });
+ }
+
[Fact, WorkItem(17681, "https://github.com/dotnet/roslyn/issues/17681")]
public void Constructor_BlockBodyToExpressionBody()
{
@@ -5625,7 +7271,7 @@ public void FieldInitializerUpdate_StaticCtorUpdate1()
edits.VerifySemantics(
ActiveStatementsDescription.Empty,
- new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single()) });
+ new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) });
}
[Fact]
@@ -5638,7 +7284,7 @@ public void PropertyInitializerUpdate_StaticCtorUpdate1()
edits.VerifySemantics(
ActiveStatementsDescription.Empty,
- new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single()) });
+ new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").StaticConstructors.Single(), preserveLocalVariables: true) });
}
[Fact]
@@ -5650,7 +7296,7 @@ public void FieldInitializerUpdate_InstanceCtorUpdate_Private()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ Diagnostic(RudeEditKind.ChangingVisibility, "class C", DeletedSymbolDisplay(FeaturesResources.constructor, "C()")));
}
[Fact]
@@ -5662,7 +7308,7 @@ public void PropertyInitializerUpdate_InstanceCtorUpdate_Private()
var edits = GetTopEdits(src1, src2);
edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.constructor));
+ Diagnostic(RudeEditKind.ChangingVisibility, "class C", DeletedSymbolDisplay(FeaturesResources.constructor, "C()")));
}
[Fact]
@@ -5675,7 +7321,7 @@ public void FieldInitializerUpdate_InstanceCtorUpdate_Public()
edits.VerifySemantics(
ActiveStatementsDescription.Empty,
- new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single()) });
+ new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) });
}
[Fact]
@@ -5688,7 +7334,7 @@ public void PropertyInitializerUpdate_InstanceCtorUpdate_Public()
edits.VerifySemantics(
ActiveStatementsDescription.Empty,
- new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single()) });
+ new[] { SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").InstanceConstructors.Single(), preserveLocalVariables: true) });
}
[Fact]
@@ -5948,7 +7594,6 @@ public void FieldInitializerUpdate_StackAllocInConstructor()
edits.VerifyEdits(
"Update [a = 1]@21 -> [a = 2]@21");
- // TODO (tomat): diagnostic should point to the field initializer
edits.VerifySemanticDiagnostics(
Diagnostic(RudeEditKind.StackAllocUpdate, "stackalloc", FeaturesResources.constructor));
}
@@ -6128,8 +7773,12 @@ public void FieldInitializerUpdate_PartialTypeWithSingleDeclaration()
edits.VerifyEdits(
"Update [a = 1]@22 -> [a = 2]@22");
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.PartialTypeInitializerUpdate, "a = 2", FeaturesResources.field));
+ edits.VerifySemantics(
+ ActiveStatementsDescription.Empty,
+ new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true)
+ });
}
[Fact]
@@ -6140,8 +7789,12 @@ public void PropertyInitializerUpdate_PartialTypeWithSingleDeclaration()
var edits = GetTopEdits(src1, src2);
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.PartialTypeInitializerUpdate, "int a { get; } = 2;", FeaturesResources.auto_property));
+ edits.VerifySemantics(
+ ActiveStatementsDescription.Empty,
+ new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true)
+ });
}
[Fact]
@@ -6155,8 +7808,12 @@ public void FieldInitializerUpdate_PartialTypeWithMultipleDeclarations()
edits.VerifyEdits(
"Update [a = 1]@22 -> [a = 2]@22");
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.PartialTypeInitializerUpdate, "a = 2", FeaturesResources.field));
+ edits.VerifySemantics(
+ ActiveStatementsDescription.Empty,
+ new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true)
+ });
}
[Fact]
@@ -6167,8 +7824,12 @@ public void PropertyInitializerUpdate_PartialTypeWithMultipleDeclarations()
var edits = GetTopEdits(src1, src2);
- edits.VerifySemanticDiagnostics(
- Diagnostic(RudeEditKind.PartialTypeInitializerUpdate, "int a { get; } = 2;", FeaturesResources.auto_property));
+ edits.VerifySemantics(
+ ActiveStatementsDescription.Empty,
+ new[]
+ {
+ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(), preserveLocalVariables: true)
+ });
}
[Fact]
@@ -6803,36 +8464,83 @@ public C(bool b)
}
}
";
- var src2 = @"
-using System;
+ var src2 = @"
+using System;
+
+class B
+{
+ public B(int a) { }
+}
+
+class C : B
+{
+ static int F(Func x) => 1;
+
+ int A = F(