diff --git a/.github/ISSUE_TEMPLATE/localization-suggestion.md b/.github/ISSUE_TEMPLATE/localization-suggestion.md
index 89242dc038103..a1e2cce2e3bfc 100644
--- a/.github/ISSUE_TEMPLATE/localization-suggestion.md
+++ b/.github/ISSUE_TEMPLATE/localization-suggestion.md
@@ -40,7 +40,8 @@ https://github.com/dotnet/roslyn
---
+## Roslyn Team Instructions
A Roslyn team member will file a bug through https://aka.ms/ceLocBug which the translation team will consider.
-Internal Tracking Issue: {Update with tracking issue URL.}
\ No newline at end of file
+Internal Tracking Issue: {Update with tracking issue URL.}
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 623dd170dfb88..c207821918995 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/artifacts/bin/BuildValidator/Debug/net6.0/BuildValidator.dll",
+ "program": "${workspaceFolder}/artifacts/bin/BuildValidator/Debug/net7.0/BuildValidator.dll",
"args": [
"--assembliesPath", "./artifacts/obj/csc/Debug/net6.0",
"--referencesPath", "./artifacts/bin",
@@ -29,8 +29,8 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/artifacts/bin/RunTests/Debug/net6.0/RunTests.dll",
- "args": ["--tfm", "net6.0", "--sequential", "--html"],
+ "program": "${workspaceFolder}/artifacts/bin/RunTests/Debug/net7.0/RunTests.dll",
+ "args": ["--tfm", "net7.0", "--sequential", "--html"],
"cwd": "${workspaceFolder}/artifacts/bin/RunTests",
"stopAtEntry": false,
"console": "internalConsole"
@@ -41,7 +41,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/artifacts/bin/PrepareTests/Debug/net6.0/PrepareTests.dll",
+ "program": "${workspaceFolder}/artifacts/bin/PrepareTests/Debug/net7.0/PrepareTests.dll",
"args": [
"--source", "${workspaceFolder}",
"--destination", "${workspaceFolder}/artifacts/testPayload"
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 2cad2d7b596e2..1eaf13d9d3612 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,20 +1,6 @@
-
-
-
- 6.0.0
-
-
- 6.0.0
-
-
-
-
-
- false
-
-
+
diff --git a/Roslyn.sln b/Roslyn.sln
index 7b3342cc3ad33..6acd166b5be20 100644
--- a/Roslyn.sln
+++ b/Roslyn.sln
@@ -511,6 +511,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Compilers.Too
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.CSharp.EndToEnd.UnitTests", "src\Compilers\CSharp\Test\EndToEnd\Microsoft.CodeAnalysis.CSharp.EndToEnd.UnitTests.csproj", "{C247414A-8946-4BAB-BE1F-C82B90C63EF6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CommonLanguageServerProtocol.Framework", "src\Features\LanguageServer\Microsoft.CommonLanguageServerProtocol.Framework\Microsoft.CommonLanguageServerProtocol.Framework.csproj", "{D2589BCE-4F2E-4113-B7E7-37392C0C5492}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CommonLanguageServerProtocol.Framework.Example", "src\Features\LanguageServer\Microsoft.CommonLanguageServerProtocol.Framework.Example\Microsoft.CommonLanguageServerProtocol.Framework.Example.csproj", "{BD9539EB-AA5E-4E67-AC7F-97D7CBC4D0C9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CommonLanguageServerProtocol.Framework.UnitTests", "src\Features\LanguageServer\Microsoft.CommonLanguageServerProtocol.Framework.UnitTests\Microsoft.CommonLanguageServerProtocol.Framework.UnitTests.csproj", "{58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1241,6 +1247,18 @@ Global
{C247414A-8946-4BAB-BE1F-C82B90C63EF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C247414A-8946-4BAB-BE1F-C82B90C63EF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C247414A-8946-4BAB-BE1F-C82B90C63EF6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D2589BCE-4F2E-4113-B7E7-37392C0C5492}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D2589BCE-4F2E-4113-B7E7-37392C0C5492}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D2589BCE-4F2E-4113-B7E7-37392C0C5492}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D2589BCE-4F2E-4113-B7E7-37392C0C5492}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD9539EB-AA5E-4E67-AC7F-97D7CBC4D0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BD9539EB-AA5E-4E67-AC7F-97D7CBC4D0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD9539EB-AA5E-4E67-AC7F-97D7CBC4D0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BD9539EB-AA5E-4E67-AC7F-97D7CBC4D0C9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1473,6 +1491,9 @@ Global
{6131713D-DFB4-49B5-8010-50071FED3E85} = {C52D8057-43AF-40E6-A01B-6CDBB7301985}
{A9A8ADE5-F123-4109-9FA4-4B92F1657043} = {C52D8057-43AF-40E6-A01B-6CDBB7301985}
{C247414A-8946-4BAB-BE1F-C82B90C63EF6} = {32A48625-F0AD-419D-828B-A50BDABA38EA}
+ {D2589BCE-4F2E-4113-B7E7-37392C0C5492} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6}
+ {BD9539EB-AA5E-4E67-AC7F-97D7CBC4D0C9} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6}
+ {58AD1B2C-6FFC-47CB-838A-54D0CA2BF0C8} = {3E5FE3DB-45F7-4D83-9097-8F05D3B3AEC6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29}
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 7d98e6e0d9a82..8083649094752 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -40,6 +40,8 @@ variables:
- name: _DotNetValidationArtifactsCategory
value: .NETCoreValidation
- group: DotNet-Roslyn-SDLValidation-Params
+ - name: Codeql.Enabled
+ value: true
# To retrieve OptProf data we need to authenticate to the VS drop storage.
# Get access token with $dn-bot-devdiv-drop-rw-code-rw and dn-bot-dnceng-build-rw-code-rw from DotNet-VSTS-Infra-Access
diff --git a/azure-pipelines-pr-validation.yml b/azure-pipelines-pr-validation.yml
index f1390a9c58547..e53b7f62f4397 100644
--- a/azure-pipelines-pr-validation.yml
+++ b/azure-pipelines-pr-validation.yml
@@ -146,6 +146,15 @@ stages:
/p:IgnoreIbcMergeErrors=true
condition: succeeded()
+ - template: eng\common\templates\steps\generate-sbom.yml
+
+ - task: PowerShell@2
+ displayName: Publish Assets
+ inputs:
+ filePath: 'eng\publish-assets.ps1'
+ arguments: '-configuration $(BuildConfiguration) -branchName "$(SourceBranchName)"'
+ condition: succeeded()
+
# Publish OptProf generated JSON files as a build artifact. This allows for easy inspection from
# a build execution.
- task: PublishBuildArtifacts@1
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 2e478f2487f2c..617c0c7add041 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -38,8 +38,8 @@ stages:
testArtifactName: Transport_Artifacts_Windows_Debug
configuration: Debug
queueName: windows.vs2022preview.amd64.open
- restoreArguments: -msbuildEngine dotnet /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false
- buildArguments: -msbuildEngine dotnet /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false
+ restoreArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false
+ buildArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false
- stage: Windows_Release_Build
dependsOn: []
@@ -50,8 +50,8 @@ stages:
testArtifactName: Transport_Artifacts_Windows_Release
configuration: Release
queueName: windows.vs2022preview.amd64.open
- restoreArguments: -msbuildEngine dotnet /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false
- buildArguments: -msbuildEngine dotnet /p:UsingToolPdbConverter=false /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false
+ restoreArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false
+ buildArguments: -msbuildEngine dotnet /p:UsingToolVSSDK=false /p:GenerateSatelliteAssemblies=false /p:PublishReadyToRun=false
- stage: Unix_Build
dependsOn: []
diff --git a/docs/Breaking API Changes.md b/docs/Breaking API Changes.md
index cfdf98d31c450..994d2b6dd8d3a 100644
--- a/docs/Breaking API Changes.md
+++ b/docs/Breaking API Changes.md
@@ -64,3 +64,10 @@ Roslyn does not support implementing completion for arbitrary languages.
### `Microsoft.CodeAnalysis.CodeStyle.NotificationOption` is now immutable
All property setters now throw an exception.
+
+# Version 4.4.0
+
+`Workspace.OnWorkspaceFailed` is no longer called when an error occurs while reading source file content from disk.
+
+The `Workspace` and `DocumentId` parameters of `TextLoader.LoadTextAndVersionAsync(Workspace, DocumentId, CancellationToken)` are deprecated.
+The method now receives `null` `Workspace` and `DocumentId`.
diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
index 6d58164825c87..ee5e6ee0d1d3d 100644
--- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
+++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
@@ -102,6 +102,33 @@ Possible workarounds are:
Also, implicit conversions between `IntPtr`/`UIntPtr` and other numeric types are treated as standard
conversions on such platforms. This can affect overload resolution in some cases.
+These changes could cause a behavioral change if the user code was depending on overflow exceptions in an
+unchecked context, or if it was not expecting overflow exceptions in a checked context. An analyzer was
+[added in 7.0](https://github.com/dotnet/runtime/issues/74022) to help detect such behavioral changes
+and take appropriate action. The analyzer will produce diagnostics on potential behavioral changes, which default
+to info severity but can be upgraded to warnings via [editorconfig](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#severity-level).
+
+## Addition of System.UIntPtr and System.Int32
+
+***Introduced in .NET SDK 7.0.100, Visual Studio 2022 version 17.3.***
+
+When the platform supports __numeric__ `IntPtr` and `UIntPtr` types (as indicated by the presence of
+`System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr`), the operator `+(UIntPtr, int)` defined in `System.UIntPtr`
+can no longer be used.
+Instead, adding expressions of types `System.UIntPtr` and a `System.Int32` results in an error:
+
+```csharp
+UIntPtr M(UIntPtr x, int y)
+{
+ return x + y; // error: Operator '+' is ambiguous on operands of type 'nuint' and 'int'
+}
+```
+
+Possible workarounds are:
+
+1. Use the `UIntPtr.Add(UIntPtr, int)` method: `UIntPtr.Add(x, y)`
+2. Apply an unchecked cast to type `nuint` on the second operand: `x + unchecked((nuint)y)`
+
## Nameof operator in attribute on method or local function
***Introduced in .NET SDK 6.0.400, Visual Studio 2022 version 17.3.***
diff --git a/docs/compilers/Design/Unexpected Conditions.md b/docs/compilers/Design/Unexpected Conditions.md
index 1d6a203fd1375..e53ce20d9b4dc 100644
--- a/docs/compilers/Design/Unexpected Conditions.md
+++ b/docs/compilers/Design/Unexpected Conditions.md
@@ -2,7 +2,7 @@ These are [guidelines](https://www.youtube.com/watch?v=6GMkuPiIZ2k) for writing
- Use `Debug.Assert(Condition)` to document invariants in the code. Although these dissolve away into nothing in non-Debug builds, as an open-source project we have little control over whether our customers are running our code with Debug enabled. Therefore such assertions should not consume excessive execution time. We may consider having such assertions run in production builds in the future. If we find they are too expensive we may create work items to improve their performance.
- If you write a switch statement that is intended to be exhaustive of the possibilities, add a default branch with `throw ExceptionUtilities.UnexpectedValue(switchExpression);`.
-- Similarly, if you have a sequence of `if-then-else if` statements that is intended to be exhaustive of the possibilities, add a final "impossible" else branch with `throw ExceptionUtilities.Unreachable;` or, if is convenient to provide interesting, easy to obtain data for the diagnostic, use `ExceptionUtilities.UnexpectedValue`. Do this also for other situations where the code reaches a point that is "impossible".
+- Similarly, if you have a sequence of `if-then-else if` statements that is intended to be exhaustive of the possibilities, add a final "impossible" else branch with `throw ExceptionUtilities.Unreachable();` or, if is convenient to provide interesting, easy to obtain data for the diagnostic, use `ExceptionUtilities.UnexpectedValue`. Do this also for other situations where the code reaches a point that is "impossible".
- Validation of preconditions in public APIs should be done with plain code. Report a diagnostic if one exists for the situation (e.g. a syntax error), or throw an appropriate exception such as `ArgumentNullException` or `ArgumentException`.
- If you run into some other weird error case that would be fatal, throw `InvalidOperationException` with interesting, straightforward to get, data in the message. These should be rare and should be accompanied by a comment explaining why an `Assert` is not sufficient.
diff --git a/docs/ide/external-access.md b/docs/ide/external-access.md
index e09926a4a1de6..23fa9d46cf31b 100644
--- a/docs/ide/external-access.md
+++ b/docs/ide/external-access.md
@@ -1,5 +1,13 @@
# External Access Policies
+## API Tracking
+
+We track the APIs that we've exposed with a roslyn analyzer, which will fail the build if APIs are removed. Unlike our public APIs, we are allowed to have breaking changes here, but these will often cause insertion failures. Any removal of an existing API (whether the API is fully removed, or the parameters/return changed) needs to have sign off from the current infrastructure rotation, and will potentially require a test insertion before merging to ensure VS isn't broken, or coordinated insertion with the affected partner team.
+
+Because "shipping" for EA projects occurs every time a change is checked in, we don't bother updating the `InternalAPI.Shipped.txt` file for these projects.
+
+Every EA project has an `Internal` namespace that is considered Roslyn implementation details. For example, the OmniSharp namespace is `Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Internal`. We do not track the APIs under these namespaces, and it's on the dependent projects to not reference anything from these namespaces. Not every EA project actually uses this namespace. If an EA project that doesn't currently use their `Internal` namespace wants to start, modify `/src/Tools/ExternalAccess/.editorconfig` to set the `dotnet_public_api_analyzer.skip_namespaces` key to that namespace for the affected files. Multiple namespaces can be included by using a `,` separator.
+
## OmniSharp
When a change needs to be made to an API in the ExternalAccess.OmniSharp or ExternalAccess.OmniSharp.CSharp packages, ping @333fred, @JoeRobich, @filipw, or @david-driscoll as a heads up. Breaking changes are allowed, but please wait for acknowledgement and followup questions to ensure that we don't completely break OmniSharp scenarios.
diff --git a/docs/wiki/NuGet-packages.md b/docs/wiki/NuGet-packages.md
index 5a70764af7896..3039916c9625c 100644
--- a/docs/wiki/NuGet-packages.md
+++ b/docs/wiki/NuGet-packages.md
@@ -39,6 +39,9 @@ Below are the versions of the language available in the NuGet packages. Remember
- Version `3.10` includes C# 9.0 (Visual Studio 2019 version 16.10, .NET 5)
- Version `3.11` includes C# 9.0 (Visual Studio 2019 version 16.11, .NET 5)
- Version `4.0` includes C# 10.0 (Visual Studio 2022 version 17.0, .NET 6)
+- Version `4.1` includes C# 10.0 (Visual Studio 2022 version 17.1, .NET 6)
+- Version `4.2` includes C# 10.0 (Visual Studio 2022 version 17.2, .NET 6)
+- Version `4.3.1` includes C# 10.0 (Visual Studio 2022 version 17.3, .NET 6)
See the [history of C# language features](https://github.com/dotnet/csharplang/blob/main/Language-Version-History.md) for more details.
diff --git a/eng/Versions.props b/eng/Versions.props
index 16e299603bd7d..5fe6ee87804c8 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -6,23 +6,23 @@
-->
4
- 4
+ 5
0
- 4
+ 1
$(MajorVersion).$(MinorVersion).$(PatchVersion)
$(MajorVersion).$(MinorVersion).0.0
- 4.3.0-1.final
+ 4.4.0-2.final
- 3.3.4-beta1.22204.1
+ 3.3.4-beta1.22504.1
7.0.0-preview1.22218.1
- 1.1.2-beta1.22462.1
- 0.1.145-beta
+ 1.1.2-beta1.22512.1
+ 0.1.149-beta
4.3.0-1.final
17.4.203-preview
@@ -53,6 +53,7 @@
1.2.4
1.2.4
1.2.4
+ 1.3.0
1.2.4
0.13.0
0.13.0
@@ -61,7 +62,8 @@
2.14.1
7.1.0.6543
1.0.7
- 1.4.1
+ 1.5.5
+ 6.0.0
6.0.0
+ 6.0.0
6.0.0
4.5.0
4.5.4
- 2.0.7
+ 2.1.0
1.1.0.14
1.1.87
17.0.1056-Dev17PIAs-g9dffd635
@@ -297,7 +300,7 @@
true
- true
+ false
true
true
true
@@ -305,7 +308,6 @@
true
true
true
- true
-
-
-
-
\ No newline at end of file
diff --git a/eng/targets/Imports.BeforeArcade.targets b/eng/targets/Imports.BeforeArcade.targets
new file mode 100644
index 0000000000000..aeb820317be69
--- /dev/null
+++ b/eng/targets/Imports.BeforeArcade.targets
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ true
+ false
+ $(AssemblyName).Symbols
+ $(AssemblyName).$(PlatformTarget).Symbols
+
+
+
+
+
+ 6.0.0
+
+
+ 6.0.0
+
+
+
+
+
+ false
+
+
+
diff --git a/eng/targets/Imports.targets b/eng/targets/Imports.targets
index 0320ff6eb4dd0..e4264602c2caf 100644
--- a/eng/targets/Imports.targets
+++ b/eng/targets/Imports.targets
@@ -91,6 +91,11 @@
+
+
+
+
+
-
+
+
@@ -376,6 +381,5 @@
-
diff --git a/eng/targets/PackageProject.props b/eng/targets/PackageProject.props
index c2d3e0f0fb35d..02ad54dc28b47 100644
--- a/eng/targets/PackageProject.props
+++ b/eng/targets/PackageProject.props
@@ -11,5 +11,7 @@
$(NoWarn);NU5128
+
+ false
\ No newline at end of file
diff --git a/eng/targets/Services.props b/eng/targets/Services.props
index 40b5c278e0835..29e4ca9ea63a0 100644
--- a/eng/targets/Services.props
+++ b/eng/targets/Services.props
@@ -30,6 +30,7 @@
+
@@ -39,6 +40,7 @@
+
+ false
net46;net472
- net6.0
+ net6.0;net7.0
$(MSBuildThisFileDirectory)..\config\xunit.runner.json
$(MSBuildThisFileDirectory)..\config\xunit.runner.json
diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs
index 7b4b24d63a5c2..2ea95162a5f03 100644
--- a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs
+++ b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryCast/CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs
@@ -28,6 +28,6 @@ protected override bool IsUnnecessaryCast(SemanticModel model, ExpressionSyntax
protected override TextSpan GetFadeSpan(ExpressionSyntax node)
=> node is CastExpressionSyntax cast ? TextSpan.FromBounds(cast.OpenParenToken.SpanStart, cast.CloseParenToken.Span.End) :
- node is BinaryExpressionSyntax binary ? TextSpan.FromBounds(binary.OperatorToken.SpanStart, node.Span.End) : throw ExceptionUtilities.Unreachable;
+ node is BinaryExpressionSyntax binary ? TextSpan.FromBounds(binary.OperatorToken.SpanStart, node.Span.End) : throw ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Analyzers/CSharp/Analyzers/UseAutoProperty/CSharpUseAutoPropertyAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseAutoProperty/CSharpUseAutoPropertyAnalyzer.cs
index faedd97361eed..3e57d390a249e 100644
--- a/src/Analyzers/CSharp/Analyzers/UseAutoProperty/CSharpUseAutoPropertyAnalyzer.cs
+++ b/src/Analyzers/CSharp/Analyzers/UseAutoProperty/CSharpUseAutoPropertyAnalyzer.cs
@@ -167,7 +167,7 @@ private static bool CheckExpressionSyntactically(ExpressionSyntax expression)
case ArrowExpressionClauseSyntax arrowExpression:
return arrowExpression.Expression;
case null: return null;
- default: throw ExceptionUtilities.Unreachable;
+ default: throw ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs
index e54e88e8e1a8a..6b524ed015d6a 100644
--- a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs
+++ b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs
@@ -69,7 +69,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
{
BinaryExpressionSyntax binaryExpression => (binaryExpression.Left, (SyntaxNode)binaryExpression.Right),
IsPatternExpressionSyntax isPattern => (isPattern.Expression, isPattern.Pattern),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
var operand = GetNullCheckOperand(comparisonLeft, comparison.Kind(), comparisonRight)?.WalkDownParentheses();
if (operand == null)
diff --git a/src/Analyzers/CSharp/CodeFixes/Nullable/CSharpDeclareAsNullableCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/Nullable/CSharpDeclareAsNullableCodeFixProvider.cs
index 9dd74bea4334a..ac51b19bbcddc 100644
--- a/src/Analyzers/CSharp/CodeFixes/Nullable/CSharpDeclareAsNullableCodeFixProvider.cs
+++ b/src/Analyzers/CSharp/CodeFixes/Nullable/CSharpDeclareAsNullableCodeFixProvider.cs
@@ -46,35 +46,25 @@ public CSharpDeclareAsNullableCodeFixProvider()
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
- var diagnostic = context.Diagnostics.First();
- var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
- if (root == null)
- {
- return;
- }
-
- var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
- if (model == null)
- {
- return;
- }
+ var cancellationToken = context.CancellationToken;
- var node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
+ var model = await context.Document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+ var node = context.Diagnostics.First().Location.FindNode(getInnermostNodeForTie: true, cancellationToken);
- var declarationTypeToFix = TryGetDeclarationTypeToFix(model, node);
+ var declarationTypeToFix = TryGetDeclarationTypeToFix(model, node, cancellationToken);
if (declarationTypeToFix == null)
- {
return;
- }
RegisterCodeFix(context, CSharpCodeFixesResources.Declare_as_nullable, GetEquivalenceKey(node, model));
}
private static string GetEquivalenceKey(SyntaxNode node, SemanticModel model)
{
- return IsRemoteApiUsage(node, model) ? AssigningNullLiteralRemotelyEquivalenceKey :
- node.IsKind(SyntaxKind.ConditionalAccessExpression) ? ConditionalOperatorEquivalenceKey :
- AssigningNullLiteralLocallyEquivalenceKey;
+ return IsRemoteApiUsage(node, model)
+ ? AssigningNullLiteralRemotelyEquivalenceKey
+ : node.IsKind(SyntaxKind.ConditionalAccessExpression)
+ ? ConditionalOperatorEquivalenceKey
+ : AssigningNullLiteralLocallyEquivalenceKey;
static bool IsRemoteApiUsage(SyntaxNode node, SemanticModel model)
{
@@ -104,20 +94,21 @@ static bool IsRemoteApiUsage(SyntaxNode node, SemanticModel model)
}
protected override async Task FixAllAsync(
- Document document, ImmutableArray diagnostics,
- SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ Document document,
+ ImmutableArray diagnostics,
+ SyntaxEditor editor,
+ CodeActionOptionsProvider fallbackOptions,
+ CancellationToken cancellationToken)
{
// a method can have multiple `return null;` statements, but we should only fix its return type once
using var _ = PooledHashSet.GetInstance(out var alreadyHandled);
- var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
- if (model != null)
+ var model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+
+ foreach (var diagnostic in diagnostics)
{
- foreach (var diagnostic in diagnostics)
- {
- var node = diagnostic.Location.FindNode(getInnermostNodeForTie: true, cancellationToken);
- MakeDeclarationNullable(editor, model, node, alreadyHandled);
- }
+ var node = diagnostic.Location.FindNode(getInnermostNodeForTie: true, cancellationToken);
+ MakeDeclarationNullable(editor, model, node, alreadyHandled, cancellationToken);
}
}
@@ -127,9 +118,10 @@ protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic, Doc
return equivalenceKey == GetEquivalenceKey(node, model);
}
- private static void MakeDeclarationNullable(SyntaxEditor editor, SemanticModel model, SyntaxNode node, HashSet alreadyHandled)
+ private static void MakeDeclarationNullable(
+ SyntaxEditor editor, SemanticModel model, SyntaxNode node, HashSet alreadyHandled, CancellationToken cancellationToken)
{
- var declarationTypeToFix = TryGetDeclarationTypeToFix(model, node);
+ var declarationTypeToFix = TryGetDeclarationTypeToFix(model, node, cancellationToken);
if (declarationTypeToFix != null && alreadyHandled.Add(declarationTypeToFix))
{
var fixedDeclaration = SyntaxFactory.NullableType(declarationTypeToFix.WithoutTrivia()).WithTriviaFrom(declarationTypeToFix);
@@ -137,12 +129,11 @@ private static void MakeDeclarationNullable(SyntaxEditor editor, SemanticModel m
}
}
- private static TypeSyntax? TryGetDeclarationTypeToFix(SemanticModel model, SyntaxNode node)
+ private static TypeSyntax? TryGetDeclarationTypeToFix(
+ SemanticModel model, SyntaxNode node, CancellationToken cancellationToken)
{
if (!IsExpressionSupported(node))
- {
return null;
- }
if (node.Parent is (kind: SyntaxKind.ReturnStatement or SyntaxKind.YieldReturnStatement))
{
@@ -161,9 +152,7 @@ SyntaxKind.IndexerDeclaration or
SyntaxKind.EventDeclaration);
if (containingMember == null)
- {
return null;
- }
var onYield = node.IsParentKind(SyntaxKind.YieldReturnStatement);
@@ -191,72 +180,49 @@ SyntaxKind.IndexerDeclaration or
}
// string x = null;
- if (node.Parent?.Parent?.IsParentKind(SyntaxKind.VariableDeclaration) == true)
+ if (node.Parent?.Parent?.Parent is VariableDeclarationSyntax variableDeclaration)
{
- var variableDeclaration = (VariableDeclarationSyntax)node.Parent.Parent.Parent!;
- if (variableDeclaration.Variables.Count != 1)
- {
- // string x = null, y = null;
- return null;
- }
-
- return variableDeclaration.Type;
+ // string x = null, y = null;
+ return variableDeclaration.Variables.Count == 1 ? variableDeclaration.Type : null;
}
// x = null;
if (node.Parent is AssignmentExpressionSyntax assignment)
{
- var symbol = model.GetSymbolInfo(assignment.Left).Symbol;
- if (symbol is ILocalSymbol local)
+ var symbol = model.GetSymbolInfo(assignment.Left, cancellationToken).Symbol;
+ if (symbol is ILocalSymbol { DeclaringSyntaxReferences.Length: > 0 } local)
{
- var syntax = local.DeclaringSyntaxReferences[0].GetSyntax();
- if (syntax is VariableDeclaratorSyntax declarator &&
- declarator.Parent is VariableDeclarationSyntax declaration &&
- declaration.Variables.Count == 1)
- {
+ var syntax = local.DeclaringSyntaxReferences[0].GetSyntax(cancellationToken);
+ if (syntax is VariableDeclaratorSyntax { Parent: VariableDeclarationSyntax { Variables.Count: 1 } declaration })
return declaration.Type;
- }
}
else if (symbol is IParameterSymbol parameter)
{
- return TryGetParameterTypeSyntax(parameter);
+ return TryGetParameterTypeSyntax(parameter, cancellationToken);
}
- else if (symbol is IFieldSymbol { IsImplicitlyDeclared: false } field)
+ else if (symbol is IFieldSymbol { IsImplicitlyDeclared: false, DeclaringSyntaxReferences.Length: > 0 } field)
{
// implicitly declared fields don't have DeclaringSyntaxReferences so filter them out
- var syntax = field.DeclaringSyntaxReferences[0].GetSyntax();
- if (syntax is VariableDeclaratorSyntax declarator &&
- declarator.Parent is VariableDeclarationSyntax declaration &&
- declaration.Variables.Count == 1)
- {
+ var syntax = field.DeclaringSyntaxReferences[0].GetSyntax(cancellationToken);
+ if (syntax is VariableDeclaratorSyntax { Parent: VariableDeclarationSyntax { Variables.Count: 1 } declaration })
return declaration.Type;
- }
- else if (syntax is TupleElementSyntax tupleElement)
- {
+
+ if (syntax is TupleElementSyntax tupleElement)
return tupleElement.Type;
- }
}
- else if (symbol is IFieldSymbol { CorrespondingTupleField: IFieldSymbol tupleField })
+ else if (symbol is IFieldSymbol { CorrespondingTupleField: IFieldSymbol { Locations: [{ IsInSource: true } location] } })
{
// Assigning a tuple field, eg. foo.Item1 = null
// The tupleField won't have DeclaringSyntaxReferences because it's implicitly declared, otherwise it
// would have fallen into the branch above. We can use the Locations instead, if there is one and it's in source
- if (tupleField.Locations is { Length: 1 } &&
- tupleField.Locations[0] is { IsInSource: true } location)
- {
- if (location.FindNode(default) is TupleElementSyntax tupleElement)
- {
- return tupleElement.Type;
- }
- }
+ if (location.FindNode(cancellationToken) is TupleElementSyntax tupleElement)
+ return tupleElement.Type;
}
- else if (symbol is IPropertySymbol property)
+ else if (symbol is IPropertySymbol { DeclaringSyntaxReferences.Length: > 0 } property)
{
- var syntax = property.DeclaringSyntaxReferences[0].GetSyntax();
+ var syntax = property.DeclaringSyntaxReferences[0].GetSyntax(cancellationToken);
if (syntax is PropertyDeclarationSyntax declaration)
- {
return declaration.Type;
- }
}
return null;
@@ -265,8 +231,8 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
// Method(null)
if (node.Parent is ArgumentSyntax argument && argument.Parent?.Parent is InvocationExpressionSyntax invocation)
{
- var symbol = model.GetSymbolInfo(invocation.Expression).Symbol;
- if (symbol is not IMethodSymbol method || method.PartialImplementationPart is object)
+ var symbol = model.GetSymbolInfo(invocation.Expression, cancellationToken).Symbol;
+ if (symbol is not IMethodSymbol method || method.PartialImplementationPart is not null)
{
// We don't handle partial methods yet
return null;
@@ -275,14 +241,14 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
if (argument.NameColon?.Name is IdentifierNameSyntax { Identifier: var identifier })
{
var parameter = method.Parameters.Where(p => p.Name == identifier.Text).FirstOrDefault();
- return TryGetParameterTypeSyntax(parameter);
+ return TryGetParameterTypeSyntax(parameter, cancellationToken);
}
var index = invocation.ArgumentList.Arguments.IndexOf(argument);
if (index >= 0 && index < method.Parameters.Length)
{
var parameter = method.Parameters[index];
- return TryGetParameterTypeSyntax(parameter);
+ return TryGetParameterTypeSyntax(parameter, cancellationToken);
}
return null;
@@ -290,30 +256,23 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
// string x { get; set; } = null;
if (node.Parent?.Parent is PropertyDeclarationSyntax propertyDeclaration)
- {
return propertyDeclaration.Type;
- }
// string x { get; }
// Unassigned value that's not marked as null
if (node is PropertyDeclarationSyntax propertyDeclarationSyntax)
- {
return propertyDeclarationSyntax.Type;
- }
// string x;
// Unassigned value that's not marked as null
- if (node is VariableDeclaratorSyntax { Parent: VariableDeclarationSyntax { Parent: FieldDeclarationSyntax _ } declarationSyntax } &&
- declarationSyntax.Variables.Count == 1)
- {
+ if (node is VariableDeclaratorSyntax { Parent: VariableDeclarationSyntax { Parent: FieldDeclarationSyntax, Variables.Count: 1 } declarationSyntax })
return declarationSyntax.Type;
- }
// void M(string x = null) { }
if (node.Parent?.Parent is ParameterSyntax optionalParameter)
{
- var parameterSymbol = model.GetDeclaredSymbol(optionalParameter);
- return TryGetParameterTypeSyntax(parameterSymbol);
+ var parameterSymbol = model.GetDeclaredSymbol(optionalParameter, cancellationToken);
+ return TryGetParameterTypeSyntax(parameterSymbol, cancellationToken);
}
// static string M() => null;
@@ -350,9 +309,7 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
case GenericNameSyntax generic:
var typeArguments = generic.TypeArgumentList.Arguments;
if (typeArguments.Count == 1)
- {
return typeArguments[0];
- }
break;
}
@@ -360,10 +317,9 @@ declarator.Parent is VariableDeclarationSyntax declaration &&
return null;
}
- static TypeSyntax? TryGetParameterTypeSyntax(IParameterSymbol? parameterSymbol)
+ static TypeSyntax? TryGetParameterTypeSyntax(IParameterSymbol? parameterSymbol, CancellationToken cancellationToken)
{
- if (parameterSymbol is object &&
- parameterSymbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() is ParameterSyntax parameterSyntax &&
+ if (parameterSymbol?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(cancellationToken) is ParameterSyntax parameterSyntax &&
parameterSymbol.ContainingSymbol is IMethodSymbol method &&
method.GetAllMethodSymbolsOfPartialParts().Length == 1)
{
diff --git a/src/Analyzers/CSharp/CodeFixes/RemoveUnusedParametersAndValues/CSharpRemoveUnusedValuesCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/RemoveUnusedParametersAndValues/CSharpRemoveUnusedValuesCodeFixProvider.cs
index 9ab316e351749..e27e5524a7790 100644
--- a/src/Analyzers/CSharp/CodeFixes/RemoveUnusedParametersAndValues/CSharpRemoveUnusedValuesCodeFixProvider.cs
+++ b/src/Analyzers/CSharp/CodeFixes/RemoveUnusedParametersAndValues/CSharpRemoveUnusedValuesCodeFixProvider.cs
@@ -8,7 +8,6 @@
using System.Composition;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Formatting;
@@ -17,7 +16,6 @@
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.RemoveUnusedParametersAndValues;
-using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnusedParametersAndValues
@@ -57,6 +55,21 @@ protected override SyntaxNode TryUpdateNameForFlaggedNode(SyntaxNode node, Synta
case SyntaxKind.VariableDeclarator:
var variableDeclarator = (VariableDeclaratorSyntax)node;
+ if (newName.ValueText == AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.DiscardVariableName &&
+ variableDeclarator.Initializer?.Value is ImplicitObjectCreationExpressionSyntax implicitObjectCreation &&
+ variableDeclarator.Parent is VariableDeclarationSyntax parent)
+ {
+ // If we are generating a discard on the left of an initialization with an implicit object creation on the right,
+ // then we need to replace the implicit object creation with an explicit one.
+ // For example: 'TypeName v = new();' must be changed to '_ = new TypeName();'
+ var objectCreationNode = SyntaxFactory.ObjectCreationExpression(
+ newKeyword: implicitObjectCreation.NewKeyword,
+ type: parent.Type,
+ argumentList: implicitObjectCreation.ArgumentList,
+ initializer: implicitObjectCreation.Initializer);
+ variableDeclarator = variableDeclarator.WithInitializer(variableDeclarator.Initializer.WithValue(objectCreationNode));
+ }
+
return variableDeclarator.WithIdentifier(newName.WithTriviaFrom(variableDeclarator.Identifier));
case SyntaxKind.SingleVariableDesignation:
@@ -79,7 +92,7 @@ protected override SyntaxNode TryUpdateNameForFlaggedNode(SyntaxNode node, Synta
}
}
- protected override SyntaxNode TryUpdateParentOfUpdatedNode(SyntaxNode parent, SyntaxNode newNameNode, SyntaxEditor editor, ISyntaxFacts syntaxFacts)
+ protected override SyntaxNode TryUpdateParentOfUpdatedNode(SyntaxNode parent, SyntaxNode newNameNode, SyntaxEditor editor, ISyntaxFacts syntaxFacts, SemanticModel semanticModel)
{
if (newNameNode.IsKind(SyntaxKind.DiscardDesignation)
&& parent is DeclarationPatternSyntax declarationPattern
@@ -91,6 +104,21 @@ protected override SyntaxNode TryUpdateParentOfUpdatedNode(SyntaxNode parent, Sy
return SyntaxFactory.TypePattern(declarationPattern.Type).WithTrailingTrivia(trailingTrivia);
}
+ else if (parent is AssignmentExpressionSyntax assignment &&
+ assignment.Right is ImplicitObjectCreationExpressionSyntax implicitObjectCreation &&
+ newNameNode is IdentifierNameSyntax { Identifier.ValueText: AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.DiscardVariableName } &&
+ semanticModel.GetTypeInfo(implicitObjectCreation).Type is { } type)
+ {
+ // If we are generating a discard on the left of an assignment with an implicit object creation on the right,
+ // then we need to replace the implicit object creation with an explicit one.
+ // For example: 'v = new();' must be changed to '_ = new TypeOfV();'
+ var objectCreationNode = SyntaxFactory.ObjectCreationExpression(
+ newKeyword: implicitObjectCreation.NewKeyword,
+ type: type.GenerateTypeSyntax(allowVar: false),
+ argumentList: implicitObjectCreation.ArgumentList,
+ initializer: implicitObjectCreation.Initializer);
+ return assignment.Update((ExpressionSyntax)newNameNode, assignment.OperatorToken, objectCreationNode);
+ }
return null;
}
@@ -171,7 +199,7 @@ protected override SyntaxNode GetReplacementNodeForCompoundAssignment(
protected override SyntaxNode GetReplacementNodeForVarPattern(SyntaxNode originalVarPattern, SyntaxNode newNameNode)
{
if (originalVarPattern is not VarPatternSyntax pattern)
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
// If the replacement node is DiscardDesignationSyntax
// then we need to just change the incoming var's pattern designation
diff --git a/src/Analyzers/CSharp/CodeFixes/UseIndexOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseIndexOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs
index 6c3690198589e..8768276dca2ab 100644
--- a/src/Analyzers/CSharp/CodeFixes/UseIndexOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs
+++ b/src/Analyzers/CSharp/CodeFixes/UseIndexOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs
@@ -128,7 +128,7 @@ private static RangeExpressionSyntax CreateRangeExpression(Result result, Syntax
{
ResultKind.Computed => CreateComputedRange(result),
ResultKind.Constant => CreateConstantRange(result, generator),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
private static RangeExpressionSyntax CreateComputedRange(Result result)
diff --git a/src/Analyzers/CSharp/CodeFixes/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckCodeFixProvider.cs
index 427a54cecdbc7..d6cf8b7be03e6 100644
--- a/src/Analyzers/CSharp/CodeFixes/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckCodeFixProvider.cs
+++ b/src/Analyzers/CSharp/CodeFixes/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckCodeFixProvider.cs
@@ -58,7 +58,7 @@ protected override Task FixAllAsync(
UnaryPatternSyntax =>
s_nullConstantPattern,
// The analyzer reports diagnostic only on BinaryExpressionSyntax and UnaryPatternSyntax.
- _ => throw ExceptionUtilities.Unreachable
+ _ => throw ExceptionUtilities.Unreachable()
};
editor.ReplaceNode(node, replacement.WithTriviaFrom(node));
diff --git a/src/Analyzers/CSharp/CodeFixes/UseUtf8StringLiteral/UseUtf8StringLiteralCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseUtf8StringLiteral/UseUtf8StringLiteralCodeFixProvider.cs
index 2e38282fe2e56..557bbbe3f7d65 100644
--- a/src/Analyzers/CSharp/CodeFixes/UseUtf8StringLiteral/UseUtf8StringLiteralCodeFixProvider.cs
+++ b/src/Analyzers/CSharp/CodeFixes/UseUtf8StringLiteral/UseUtf8StringLiteralCodeFixProvider.cs
@@ -102,7 +102,7 @@ private static IArrayCreationOperation GetArrayCreationOperation(SemanticModel s
var operationLocationString = diagnostic.Properties[nameof(UseUtf8StringLiteralDiagnosticAnalyzer.ArrayCreationOperationLocation)];
if (!Enum.TryParse(operationLocationString, out UseUtf8StringLiteralDiagnosticAnalyzer.ArrayCreationOperationLocation operationLocation))
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
// Because we get the location from an IOperation.Syntax, sometimes we have to look a
// little harder to get back from syntax to the operation that triggered the diagnostic
@@ -136,7 +136,7 @@ static IArrayCreationOperation FindArrayCreationOperationAncestor(IOperation ope
operation = operation.Parent!;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Analyzers/CSharp/Tests/Formatting/FormattingAnalyzerTests.cs b/src/Analyzers/CSharp/Tests/Formatting/FormattingAnalyzerTests.cs
index cc7db15e377e4..07962bbcd8453 100644
--- a/src/Analyzers/CSharp/Tests/Formatting/FormattingAnalyzerTests.cs
+++ b/src/Analyzers/CSharp/Tests/Formatting/FormattingAnalyzerTests.cs
@@ -316,5 +316,172 @@ void MyMethod()
FixedState = { Sources = { fixedCode } },
}.RunAsync();
}
+
+ [Fact]
+ public async Task TestRegion()
+ {
+ var testCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+ #region ABC1
+ System.Console.WriteLine();
+ #endregion
+ }
+#else
+ public void M()
+ {
+ #region ABC2
+ System.Console.WriteLine();
+ #endregion
+ }
+#endif
+}
+";
+ await Verify.VerifyCodeFixAsync(testCode, testCode);
+ }
+
+ [Fact]
+ public async Task TestRegion2()
+ {
+ var testCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+[||]#region OUTER1
+ #region ABC1
+ System.Console.WriteLine();
+ #endregion
+[||]#endregion
+ }
+#else
+ public void M()
+ {
+#region OUTER2
+ #region ABC2
+ System.Console.WriteLine();
+ #endregion
+#endregion
+ }
+#endif
+}
+";
+
+ var fixedCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+ #region OUTER1
+ #region ABC1
+ System.Console.WriteLine();
+ #endregion
+ #endregion
+ }
+#else
+ public void M()
+ {
+#region OUTER2
+ #region ABC2
+ System.Console.WriteLine();
+ #endregion
+#endregion
+ }
+#endif
+}
+";
+ await Verify.VerifyCodeFixAsync(testCode, fixedCode);
+ }
+
+ [Fact]
+ public async Task TestRegion3()
+ {
+ var testCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+[||]#region ABC1
+ System.Console.WriteLine();
+[||]#endregion
+ }
+#else
+ public void M()
+ {
+#region ABC2
+ System.Console.WriteLine();
+#endregion
+ }
+#endif
+}
+";
+ var fixedCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+ #region ABC1
+ System.Console.WriteLine();
+ #endregion
+ }
+#else
+ public void M()
+ {
+#region ABC2
+ System.Console.WriteLine();
+#endregion
+ }
+#endif
+}
+";
+ await Verify.VerifyCodeFixAsync(testCode, fixedCode);
+ }
+
+ [Fact]
+ public async Task TestRegion4()
+ {
+ var testCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+[||]#region ABC1
+ System.Console.WriteLine();
+[||]#endregion
+ }
+#else
+ #region ABC2
+ public void M() { }
+ #endregion
+#endif
+}
+";
+ var fixedCode = @"
+class MyClass
+{
+#if true
+ public void M()
+ {
+ #region ABC1
+ System.Console.WriteLine();
+ #endregion
+ }
+#else
+ #region ABC2
+ public void M() { }
+ #endregion
+#endif
+}
+";
+ await Verify.VerifyCodeFixAsync(testCode, fixedCode);
+ }
}
}
diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs
index 1384f6399e704..671d5bc9a4ae8 100644
--- a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs
+++ b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs
@@ -493,7 +493,7 @@ int M()
return x;
}
}", iterations: 1),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
await new VerifyCS.Test
@@ -551,7 +551,7 @@ int M()
return x;
}
}", iterations: 1),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
await new VerifyCS.Test
@@ -1066,7 +1066,7 @@ int M(int {|IDE0060:x|}, int {|IDE0060:y|})
return x;
}
}", iterations: 1),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
var test = new VerifyCS.Test
@@ -1161,7 +1161,7 @@ int M(int {|IDE0060:x|}, int {|IDE0060:y|})
int M2() => 0;
}",
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
var test = new VerifyCS.Test
@@ -1240,7 +1240,7 @@ void M(int x)
_ = {prefix}x{postfix};
}}
}}",
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
var test = new VerifyCS.Test
@@ -1357,7 +1357,7 @@ void M(int x)
int M2() => 0;
}}",
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
var test = new VerifyCS.Test
@@ -2571,7 +2571,7 @@ void M(object p)
};
}
}", iterations: 1),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
await new VerifyCS.Test
@@ -2770,7 +2770,7 @@ bool M(object p1, object p2)
return isZero;
}
}",
- _ => throw ExceptionUtilities.Unreachable
+ _ => throw ExceptionUtilities.Unreachable()
};
await new VerifyCS.Test
@@ -2895,7 +2895,7 @@ bool M2(out int x)
return false;
}
}",
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
await new VerifyCS.Test
@@ -3046,7 +3046,7 @@ bool M2(int {|IDE0060:x|})
return false;
}
}",
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
var test = new VerifyCS.Test
@@ -7805,7 +7805,7 @@ void M(object p)
};
}
}", iterations: 1),
- _ => throw ExceptionUtilities.Unreachable,
+ _ => throw ExceptionUtilities.Unreachable(),
};
await new VerifyCS.Test
@@ -8846,5 +8846,73 @@ void M()
}
}", optionName);
}
+
+ [Fact]
+ [WorkItem(64291, "https://github.com/dotnet/roslyn/issues/64291")]
+ public async Task TestImplicitObjectCreationInInitialization()
+ {
+ var source =
+@"class C
+{
+ void M()
+ {
+ C {|IDE0059:c|} = new();
+ }
+}";
+ var fixedSource =
+@"class C
+{
+ void M()
+ {
+ _ = new C();
+ }
+}";
+
+ await new VerifyCS.Test
+ {
+ TestCode = source,
+ FixedCode = fixedSource,
+ Options =
+ {
+ { CSharpCodeStyleOptions.UnusedValueAssignment, UnusedValuePreference.DiscardVariable },
+ },
+ LanguageVersion = LanguageVersion.CSharp9,
+ }.RunAsync();
+ }
+
+ [Fact]
+ [WorkItem(64291, "https://github.com/dotnet/roslyn/issues/64291")]
+ public async Task TestImplicitObjectCreationInAssignement()
+ {
+ var source =
+@"class C
+{
+ void M(C c)
+ {
+ System.Console.WriteLine(c);
+ {|IDE0059:c|} = new();
+ }
+}";
+ var fixedSource =
+@"class C
+{
+ void M(C c)
+ {
+ System.Console.WriteLine(c);
+ _ = new C();
+ }
+}";
+
+ await new VerifyCS.Test
+ {
+ TestCode = source,
+ FixedCode = fixedSource,
+ Options =
+ {
+ { CSharpCodeStyleOptions.UnusedValueAssignment, UnusedValuePreference.DiscardVariable },
+ },
+ LanguageVersion = LanguageVersion.CSharp9,
+ }.RunAsync();
+ }
}
}
diff --git a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs
index a969cb9269afa..774adb6626819 100644
--- a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs
+++ b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs
@@ -77,6 +77,64 @@ void M(object x)
}.RunAsync();
}
+ [Fact, WorkItem(64292, "https://github.com/dotnet/roslyn/issues/64292")]
+ public async Task BooleanValueConstantPattern()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode =
+@"class C
+{
+ void M(bool x)
+ {
+ if (!(x [|is|] true))
+ {
+ }
+ }
+}",
+ FixedCode =
+@"class C
+{
+ void M(bool x)
+ {
+ if (x is false)
+ {
+ }
+ }
+}",
+ LanguageVersion = LanguageVersion.CSharp9,
+ }.RunAsync();
+ }
+
+ [Fact, WorkItem(64292, "https://github.com/dotnet/roslyn/issues/64292")]
+ public async Task NonBooleanValueConstantPattern()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode =
+@"class C
+{
+ void M(object x)
+ {
+ if (!(x [|is|] true))
+ {
+ }
+ }
+}",
+ FixedCode =
+@"class C
+{
+ void M(object x)
+ {
+ if (x is not true)
+ {
+ }
+ }
+}",
+ LanguageVersion = LanguageVersion.CSharp9,
+ }.RunAsync();
+ }
+
[Fact, WorkItem(46699, "https://github.com/dotnet/roslyn/issues/46699")]
public async Task UseNotPattern()
{
diff --git a/src/Analyzers/Core/Analyzers/AnalyzersResources.resx b/src/Analyzers/Core/Analyzers/AnalyzersResources.resx
index 2fe0d502ea103..2b95225ec9034 100644
--- a/src/Analyzers/Core/Analyzers/AnalyzersResources.resx
+++ b/src/Analyzers/Core/Analyzers/AnalyzersResources.resx
@@ -241,8 +241,11 @@
Convert to conditional expression
-
- Use coalesce expression
+
+ Use coalesce expression for non-nullable types
+
+
+ Use coalesce expression for nullable types
Changes to expression trees may result in behavior changes at runtime
diff --git a/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs b/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs
index cbacab08de4a6..9602b39e82a46 100644
--- a/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs
+++ b/src/Analyzers/Core/Analyzers/Helpers/DiagnosticHelper.cs
@@ -273,7 +273,7 @@ public static Diagnostic CreateWithMessage(
}
Debug.Assert(id.StartsWith("IDE", StringComparison.Ordinal));
- return $"https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/{id.ToLowerInvariant()}";
+ return $"https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/{id.ToLowerInvariant()}";
}
public sealed class LocalizableStringWithArguments : LocalizableString, IObjectWritable
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/SuppressMessageAttributeState.cs b/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/SuppressMessageAttributeState.cs
index 8f8c2f0b8f667..59e5a75488ce8 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/SuppressMessageAttributeState.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/SuppressMessageAttributeState.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Immutable;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Microsoft.CodeAnalysis.Operations;
@@ -53,22 +54,18 @@ public bool IsSuppressMessageAttributeWithNamedArguments(
CancellationToken cancellationToken,
out ImmutableArray<(string name, IOperation value)> namedAttributeArguments)
{
- var attribute = model.GetOperation(attributeSyntax, cancellationToken);
- if (attribute == null)
+ var operation = (model.GetOperation(attributeSyntax, cancellationToken) as IAttributeOperation)?.Operation;
+ if (operation is not IObjectCreationOperation { Initializer: { } initializerOperation })
{
namedAttributeArguments = ImmutableArray<(string name, IOperation value)>.Empty;
return false;
}
- // Workaround for https://github.com/dotnet/roslyn/issues/18198
- // Use 'IOperation.Children' to get named attribute arguments.
- // Each named attribute argument is represented as an 'ISimpleAssignmentOperation'
- // with a constant value assignment to an 'IPropertyReferenceOperation' in the operation tree.
using var _ = ArrayBuilder<(string name, IOperation value)>.GetInstance(out var builder);
- foreach (var childOperation in attribute.ChildOperations)
+ foreach (var initializer in initializerOperation.Initializers)
{
- if (childOperation is ISimpleAssignmentOperation simpleAssignment &&
- simpleAssignment.Target is IPropertyReferenceOperation propertyReference &&
+ var simpleAssignment = (ISimpleAssignmentOperation)initializer;
+ if (simpleAssignment.Target is IPropertyReferenceOperation propertyReference &&
_suppressMessageAttributeType.Equals(propertyReference.Property.ContainingType))
{
builder.Add((propertyReference.Property.Name, simpleAssignment.Value));
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs
index 52fb5b1a6786e..4ced79a25386e 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs
@@ -183,27 +183,14 @@ private void RegisterActions(CompilationStartAnalysisContext compilationStartCon
// We do so to ensure that we don't report false positives during editing scenarios in the IDE, where the user
// is still editing code and fixing unresolved references to symbols, such as overload resolution errors.
// 2. Dynamic operations, where we do not know the exact member being referenced at compile time.
- // 3. Operations with OperationKind.None which are not operation root nodes. Attributes
- // generate operation blocks with root operation with OperationKind.None, and we don't want to bail out for them.
- symbolStartContext.RegisterOperationAction(_ => hasUnsupportedOperation = true, OperationKind.Invalid,
+ // 3. Operations with OperationKind.None.
+ symbolStartContext.RegisterOperationAction(_ => hasUnsupportedOperation = true, OperationKind.Invalid, OperationKind.None,
OperationKind.DynamicIndexerAccess, OperationKind.DynamicInvocation, OperationKind.DynamicMemberReference, OperationKind.DynamicObjectCreation);
- symbolStartContext.RegisterOperationAction(AnalyzeOperationNone, OperationKind.None);
symbolStartContext.RegisterSymbolEndAction(symbolEndContext => OnSymbolEnd(symbolEndContext, hasUnsupportedOperation));
// Register custom language-specific actions, if any.
_analyzer.HandleNamedTypeSymbolStart(symbolStartContext, onSymbolUsageFound);
-
- return;
-
- void AnalyzeOperationNone(OperationAnalysisContext context)
- {
- if (context.Operation.Kind == OperationKind.None &&
- context.Operation.Parent != null)
- {
- hasUnsupportedOperation = true;
- }
- }
}, SymbolKind.NamedType);
}
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
index 50d34cba2d253..17a689972a9d3 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
@@ -402,9 +402,9 @@ private bool ShouldAnalyze(IOperation operationBlock, ISymbol owningSymbol, ref
{
switch (operationBlock.Kind)
{
- case OperationKind.None:
+ case OperationKind.Attribute:
case OperationKind.ParameterInitializer:
- // Skip blocks from attributes (which have OperationKind.None) and parameter initializers.
+ // Skip blocks from attributes and parameter initializers.
// We don't have any unused values in such operation blocks.
return false;
diff --git a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs
index ae2ed8dc17b39..cf3bc70260a1d 100644
--- a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs
@@ -26,7 +26,7 @@ protected AbstractUseCoalesceExpressionDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseCoalesceExpressionDiagnosticId,
EnforceOnBuildValues.UseCoalesceExpression,
CodeStyleOptions2.PreferCoalesceExpression,
- new LocalizableResourceString(nameof(AnalyzersResources.Use_coalesce_expression), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)),
+ new LocalizableResourceString(nameof(AnalyzersResources.Use_coalesce_expression_for_non_nullable_types), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)),
new LocalizableResourceString(nameof(AnalyzersResources.Null_check_can_be_simplified), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)))
{
}
diff --git a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs
index 6bbc28f17449d..73811303fb44d 100644
--- a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs
@@ -28,7 +28,7 @@ protected AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseCoalesceExpressionForNullableDiagnosticId,
EnforceOnBuildValues.UseCoalesceExpressionForNullable,
CodeStyleOptions2.PreferCoalesceExpression,
- new LocalizableResourceString(nameof(AnalyzersResources.Use_coalesce_expression), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)))
+ new LocalizableResourceString(nameof(AnalyzersResources.Use_coalesce_expression_for_nullable_types), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)))
{
}
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf
index dbe39341d7a28..34649f526b410 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.cs.xlf
@@ -372,9 +372,14 @@
Použít automatickou vlastnost
-
-
- Použít slučovací výraz
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf
index 7a5c52184e429..6e20444003145 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.de.xlf
@@ -372,9 +372,14 @@
Automatisch generierte Eigenschaft verwenden
-
-
- COALESCE-Ausdruck verwenden
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf
index 96374efdf6de1..b7808c755aa85 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.es.xlf
@@ -372,9 +372,14 @@
Usar propiedad automática
-
-
- Usar expresión coalesce
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf
index 38d06337e925c..165f75f2a59bf 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.fr.xlf
@@ -372,9 +372,14 @@
Utiliser auto-property
-
-
- Utiliser l'expression de fusion
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf
index d995aee740491..387574e6d34e2 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.it.xlf
@@ -372,9 +372,14 @@
Usa la proprietà automatica
-
-
- Usa l'espressione COALESCE
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf
index 1ce40775d3446..b028629812d98 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ja.xlf
@@ -372,9 +372,14 @@
自動プロパティを使用する
-
-
- coalesce 式を使用します
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf
index 3055f27049dff..2839e06ecd69b 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ko.xlf
@@ -372,9 +372,14 @@
auto 속성 사용
-
-
- COALESCE 식 사용
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf
index 67e6629342339..3d7aa2b5fb641 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pl.xlf
@@ -372,9 +372,14 @@
Użyj właściwości automatycznej
-
-
- Użyj wyrażenia łączącego
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf
index e1bd13c2fe484..e4bb1a9d78802 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.pt-BR.xlf
@@ -372,9 +372,14 @@
Usar a propriedade auto
-
-
- Usar a expressão de união
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf
index a8a8331b34ae1..0fc5b6455f248 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.ru.xlf
@@ -372,9 +372,14 @@
Использовать свойство auto
-
-
- Используйте выражение объединения
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf
index dba5285e7521b..b360d981e938d 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.tr.xlf
@@ -372,9 +372,14 @@
Otomatik özellik kullan
-
-
- Birleştirme ifadesi kullan
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf
index e92f32eb09486..8cd403761aae1 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hans.xlf
@@ -372,9 +372,14 @@
使用自动属性
-
-
- 使用 COALESCE 表达式
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf
index 838e98805701d..45dcea01c1118 100644
--- a/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf
+++ b/src/Analyzers/Core/Analyzers/xlf/AnalyzersResources.zh-Hant.xlf
@@ -372,9 +372,14 @@
使用 Auto 屬性
-
-
- 使用 coalesce 運算式
+
+
+ Use coalesce expression for non-nullable types
+
+
+
+
+ Use coalesce expression for nullable types
diff --git a/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchExpressionCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchExpressionCodeFixProvider.cs
index 4cf9189e75c35..21fceb99e256f 100644
--- a/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchExpressionCodeFixProvider.cs
+++ b/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchExpressionCodeFixProvider.cs
@@ -41,7 +41,7 @@ protected sealed override void FixOneDiagnostic(
}
protected sealed override ITypeSymbol GetSwitchType(ISwitchExpressionOperation switchExpression)
- => switchExpression.Value.Type ?? throw ExceptionUtilities.Unreachable;
+ => switchExpression.Value.Type ?? throw ExceptionUtilities.Unreachable();
protected sealed override ICollection GetMissingEnumMembers(ISwitchExpressionOperation switchOperation)
=> PopulateSwitchExpressionHelpers.GetMissingEnumMembers(switchOperation);
diff --git a/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs
index c742996ebe5ad..8fe0a1960550f 100644
--- a/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs
+++ b/src/Analyzers/Core/CodeFixes/PopulateSwitch/AbstractPopulateSwitchStatementCodeFixProvider.cs
@@ -57,7 +57,7 @@ protected sealed override void FixOneDiagnostic(
}
protected sealed override ITypeSymbol GetSwitchType(ISwitchOperation switchOperation)
- => switchOperation.Value.Type ?? throw ExceptionUtilities.Unreachable;
+ => switchOperation.Value.Type ?? throw ExceptionUtilities.Unreachable();
protected sealed override ICollection GetMissingEnumMembers(ISwitchOperation switchOperation)
=> PopulateSwitchStatementHelpers.GetMissingEnumMembers(switchOperation);
diff --git a/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs
index 50e27fe76c1e3..ff66a335a3136 100644
--- a/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs
+++ b/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs
@@ -117,9 +117,10 @@ protected abstract SyntaxNode GetReplacementNodeForCompoundAssignment(
/// The rewritten node produced by .
/// The syntax editor for the code fix.
/// The syntax facts for the current language.
+ /// Semantic model for the tree.
/// The replacement node to use in the rewritten syntax tree; otherwise, to only
/// rewrite the node originally rewritten by .
- protected virtual SyntaxNode? TryUpdateParentOfUpdatedNode(SyntaxNode parent, SyntaxNode newNameNode, SyntaxEditor editor, ISyntaxFacts syntaxFacts) => null;
+ protected virtual SyntaxNode? TryUpdateParentOfUpdatedNode(SyntaxNode parent, SyntaxNode newNameNode, SyntaxEditor editor, ISyntaxFacts syntaxFacts, SemanticModel semanticModel) => null;
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
@@ -363,7 +364,7 @@ await FixAllValueAssignedIsUnusedDiagnosticsAsync(
break;
default:
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
@@ -554,7 +555,7 @@ private async Task FixAllValueAssignedIsUnusedDiagnosticsAsync(
}
else
{
- var newParentNode = TryUpdateParentOfUpdatedNode(node.GetRequiredParent(), newNameNode, editor, syntaxFacts);
+ var newParentNode = TryUpdateParentOfUpdatedNode(node.GetRequiredParent(), newNameNode, editor, syntaxFacts, semanticModel);
if (newParentNode is not null)
{
nodeReplacementMap.Add(node.GetRequiredParent(), newParentNode);
diff --git a/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionCodeFixProvider.cs
index 7f16853543de6..4199da1d4392c 100644
--- a/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionCodeFixProvider.cs
+++ b/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionCodeFixProvider.cs
@@ -35,7 +35,7 @@ protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
- RegisterCodeFix(context, AnalyzersResources.Use_coalesce_expression, nameof(AnalyzersResources.Use_coalesce_expression));
+ RegisterCodeFix(context, AnalyzersResources.Use_coalesce_expression_for_non_nullable_types, nameof(AnalyzersResources.Use_coalesce_expression_for_non_nullable_types));
return Task.CompletedTask;
}
diff --git a/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionForNullableCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionForNullableCodeFixProvider.cs
index 0ff82175f3db5..959f85bbd9d82 100644
--- a/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionForNullableCodeFixProvider.cs
+++ b/src/Analyzers/Core/CodeFixes/UseCoalesceExpression/UseCoalesceExpressionForNullableCodeFixProvider.cs
@@ -34,7 +34,7 @@ protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
- RegisterCodeFix(context, AnalyzersResources.Use_coalesce_expression, nameof(AnalyzersResources.Use_coalesce_expression));
+ RegisterCodeFix(context, AnalyzersResources.Use_coalesce_expression_for_nullable_types, nameof(AnalyzersResources.Use_coalesce_expression_for_nullable_types));
return Task.CompletedTask;
}
diff --git a/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj b/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj
index 2fdb18fb43146..3c72c53510748 100644
--- a/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj
+++ b/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj
@@ -6,7 +6,9 @@
Microsoft.CodeAnalysis.CSharp
netstandard2.0
$(DefineConstants),CODE_STYLE
- Microsoft.CodeAnalysis.CSharp.CodeStyle.NewNameSinceWeReferenceTheAnalyzersAndNuGetCannotFigureItOut
+
+
+ true
diff --git a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj
index e9db13b64fa61..823ae3c272bd4 100644
--- a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj
+++ b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj
@@ -8,6 +8,9 @@
$(DefineConstants),CODE_STYLE
true
true
+
+
+ true
diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj
index 4b21116e59957..256a85df30982 100644
--- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj
+++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj
@@ -6,6 +6,9 @@
Microsoft.CodeAnalysis
netstandard2.0
$(DefineConstants),CODE_STYLE
+
+
+ true
diff --git a/src/CodeStyle/Tools/CodeStyleConfigFileGenerator.csproj b/src/CodeStyle/Tools/CodeStyleConfigFileGenerator.csproj
index 91956df402f6b..6a3b665477240 100644
--- a/src/CodeStyle/Tools/CodeStyleConfigFileGenerator.csproj
+++ b/src/CodeStyle/Tools/CodeStyleConfigFileGenerator.csproj
@@ -5,6 +5,7 @@
true
false
true
+ false
diff --git a/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj b/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj
index cb9bb6dc23773..93ac5bfd60654 100644
--- a/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj
+++ b/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj
@@ -6,7 +6,9 @@
netstandard2.0
$(DefineConstants),CODE_STYLE
- Microsoft.CodeAnalysis.VisualBasic.CodeStyle.NewNameSinceWeReferenceTheAnalyzersAndNuGetCannotFigureItOut
+
+
+ true
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs b/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs
index d4b69a43728e3..fec144cb2a8c9 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder.QueryUnboundLambdaState.cs
@@ -75,7 +75,7 @@ protected override BoundExpression GetLambdaExpressionBody(BoundBlock body)
protected override BoundBlock CreateBlockFromLambdaExpressionBody(Binder lambdaBodyBinder, BoundExpression expression, BindingDiagnosticBag diagnostics)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, BindingDiagnosticBag diagnostics)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
index 85ca05713c6ae..fad2311e3aedf 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
@@ -2026,7 +2026,7 @@ static void getArgList(
/// whether analysis should consider value or ref escape. Not all method arguments
/// are included, and some arguments may be included twice - once for value, once for ref.
///
- private void GetFilteredInvocationArgumentsForEscapeWithUpdatedRules(
+ private static void GetFilteredInvocationArgumentsForEscapeWithUpdatedRules(
Symbol symbol,
BoundExpression? receiver,
ImmutableArray parameters,
@@ -2102,7 +2102,7 @@ static bool hasRefLikeReturn(Symbol symbol)
/// Optionally this will also return all of the that
/// result from this invocation. That is useful for MAMM analysis.
///
- private void GetEscapeValuesForUpdatedRules(
+ private static void GetEscapeValuesForUpdatedRules(
Symbol symbol,
BoundExpression? receiver,
ImmutableArray parameters,
@@ -2687,7 +2687,7 @@ private static void ReportReadOnlyError(Symbol symbol, SyntaxNode node, BindValu
};
int index = (checkingReceiver ? 3 : 0) + (kind == BindValueKind.RefReturn ? 0 : (RequiresRefOrOut(kind) ? 1 : 2));
- Error(diagnostics, ReadOnlyErrors[index], node, symbolKind, symbol);
+ Error(diagnostics, ReadOnlyErrors[index], node, symbolKind, new FormattedSymbol(symbol, SymbolDisplayFormat.ShortFormat));
}
///
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
index eaf71ea3657e0..70390a2a15383 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
@@ -409,9 +409,10 @@ private void FailRemainingInferencesAndSetValEscape(ArrayBuilder
@@ -4605,7 +4644,7 @@ private BoundObjectInitializerExpressionBase BindInitializerExpression(
return BindCollectionInitializerExpression(syntax, type, diagnostics, implicitReceiver);
default:
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
index c2e6d6bd44e09..fe8397b7765ee 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
@@ -146,7 +146,7 @@ internal static void BindRegularCSharpFieldInitializers(
break;
default:
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
index 25145ec3ad00c..455be2871a30d 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
@@ -1863,13 +1863,6 @@ private bool TryBindNameofOperator(InvocationExpressionSyntax node, BindingDiagn
if (node.MayBeNameofOperator())
{
var binder = this.GetBinder(node);
- if (binder is null)
- {
- // This could happen during speculation due to a bug
- // Tracked by https://github.com/dotnet/roslyn/issues/60801
- result = null;
- return false;
- }
if (binder.EnclosingNameofArgument == node.ArgumentList.Arguments[0].Expression)
{
result = binder.BindNameofOperatorInternal(node, diagnostics);
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs
index f6d88eb342d3b..fe66c8b9babee 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lookup.cs
@@ -1372,7 +1372,7 @@ FileIdentifier getFileIdentifierForFileTypes()
}
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
index 67cce30d275fe..03c5813e80ca7 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
@@ -4335,8 +4335,13 @@ private static ConstantValue FoldConditionalOperator(BoundExpression condition,
}
}
- private static void CheckNativeIntegerFeatureAvailability(BinaryOperatorKind operatorKind, SyntaxNode syntax, BindingDiagnosticBag diagnostics)
+ private void CheckNativeIntegerFeatureAvailability(BinaryOperatorKind operatorKind, SyntaxNode syntax, BindingDiagnosticBag diagnostics)
{
+ if (Compilation.Assembly.RuntimeSupportsNumericIntPtr)
+ {
+ return;
+ }
+
switch (operatorKind & BinaryOperatorKind.TypeMask)
{
case BinaryOperatorKind.NInt:
@@ -4346,8 +4351,13 @@ private static void CheckNativeIntegerFeatureAvailability(BinaryOperatorKind ope
}
}
- private static void CheckNativeIntegerFeatureAvailability(UnaryOperatorKind operatorKind, SyntaxNode syntax, BindingDiagnosticBag diagnostics)
+ private void CheckNativeIntegerFeatureAvailability(UnaryOperatorKind operatorKind, SyntaxNode syntax, BindingDiagnosticBag diagnostics)
{
+ if (Compilation.Assembly.RuntimeSupportsNumericIntPtr)
+ {
+ return;
+ }
+
switch (operatorKind & UnaryOperatorKind.TypeMask)
{
case UnaryOperatorKind.NInt:
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
index abaf95f3a1c82..87aa77fca3797 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
@@ -72,7 +72,7 @@ private BoundExpression MakeIsPatternExpression(
case BoundConstantPattern _:
case BoundITuplePattern _:
// these patterns can fail in practice
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
case BoundRelationalPattern _:
case BoundTypePattern _:
case BoundNegatedPattern _:
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index b4598a801e866..ecf4ddfb87653 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -1542,6 +1542,11 @@ private BoundAssignmentOperator BindAssignment(
{
if (isRef)
{
+ // https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/low-level-struct-improvements.md#rules-ref-reassignment
+ // For a ref reassignment in the form `e1 = ref e2` both of the following must be true:
+ // 1. `e2` must have *ref-safe-to-escape* at least as large as the *ref-safe-to-escape* of `e1`
+ // 2. `e1` must have the same *safe-to-escape* as `e2`
+
var leftEscape = GetRefEscape(op1, LocalScopeDepth);
var rightEscape = GetRefEscape(op2, LocalScopeDepth);
if (leftEscape < rightEscape)
@@ -1560,6 +1565,28 @@ private BoundAssignmentOperator BindAssignment(
op2 = ToBadExpression(op2);
}
}
+ else if (op1.Kind is BoundKind.Local or BoundKind.Parameter)
+ {
+ leftEscape = GetValEscape(op1, LocalScopeDepth);
+ rightEscape = GetValEscape(op2, LocalScopeDepth);
+
+ Debug.Assert(leftEscape == rightEscape || op1.Type.IsRefLikeType);
+
+ // We only check if the safe-to-escape of e2 is wider than the safe-to-escape of e1 here,
+ // we don't check for equality. The case where the safe-to-escape of e2 is narrower than
+ // e1 is handled in the if (op1.Type.IsRefLikeType) { ... } block later.
+ if (leftEscape > rightEscape)
+ {
+ Debug.Assert(op1.Kind != BoundKind.Parameter); // If the assert fails, add a corresponding test.
+
+ var errorCode = this.InUnsafeRegion ? ErrorCode.WRN_RefAssignValEscapeWider : ErrorCode.ERR_RefAssignValEscapeWider;
+ Error(diagnostics, errorCode, node, getName(op1), op2.Syntax);
+ if (!this.InUnsafeRegion)
+ {
+ op2 = ToBadExpression(op2);
+ }
+ }
+ }
}
if (op1.Type.IsRefLikeType)
@@ -3761,7 +3788,7 @@ internal virtual BoundExpressionStatement BindConstructorInitializer(Constructor
break;
default:
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/BlockBinder.cs b/src/Compilers/CSharp/Portable/Binder/BlockBinder.cs
index 78be648c8c5d2..52ea1db8a9384 100644
--- a/src/Compilers/CSharp/Portable/Binder/BlockBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/BlockBinder.cs
@@ -70,7 +70,7 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
@@ -88,7 +88,7 @@ internal override ImmutableArray GetDeclaredLocalFunctionsF
return this.LocalFunctions;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs
index ee98266fc1a45..7f328e0efd427 100644
--- a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs
@@ -154,7 +154,7 @@ internal override BoundExpression? ConditionalReceiverExpression
internal override TypeWithAnnotations GetIteratorElementType()
{
// There's supposed to be an enclosing method or lambda.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override Symbol? ContainingMemberOrLambda
@@ -177,78 +177,78 @@ internal override bool AreNullableAnnotationsGloballyEnabled()
internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundStatement BindSwitchStatementCore(SwitchStatementSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
{
// There's supposed to be a SwitchBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundExpression BindSwitchExpressionCore(SwitchExpressionSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
{
// There's supposed to be a SwitchExpressionBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabelSyntax node, BindingDiagnosticBag diagnostics)
{
// There's supposed to be a SwitchBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundSwitchExpressionArm BindSwitchExpressionArm(SwitchExpressionArmSyntax node, TypeSymbol switchGoverningType, uint switchGoverningValEscape, BindingDiagnosticBag diagnostics)
{
// There's supposed to be an overrider of this method (e.g. SwitchExpressionArmBinder) for the arm in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundForStatement BindForParts(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a ForLoopBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundStatement BindForEachParts(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a ForEachLoopBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundStatement BindForEachDeconstruction(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a ForEachLoopBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundWhileStatement BindWhileParts(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a WhileBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundDoStatement BindDoParts(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a WhileBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundStatement BindUsingStatementParts(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a UsingStatementBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override BoundStatement BindLockStatementParts(BindingDiagnosticBag diagnostics, Binder originalBinder)
{
// There's supposed to be a LockBinder (or other overrider of this method) in the chain.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableHashSet LockedOrDisposedVariables
diff --git a/src/Compilers/CSharp/Portable/Binder/CatchClauseBinder.cs b/src/Compilers/CSharp/Portable/Binder/CatchClauseBinder.cs
index 51a9e7a93f7ec..d966b29e2b6f3 100644
--- a/src/Compilers/CSharp/Portable/Binder/CatchClauseBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/CatchClauseBinder.cs
@@ -49,12 +49,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/ContextualAttributeBinder.cs b/src/Compilers/CSharp/Portable/Binder/ContextualAttributeBinder.cs
index 26afb3c266367..3b5873996b3f4 100644
--- a/src/Compilers/CSharp/Portable/Binder/ContextualAttributeBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ContextualAttributeBinder.cs
@@ -49,7 +49,7 @@ internal Symbol AttributedMember
///
/// Walk up to the nearest method/property/event.
///
- private static Symbol GetAttributedMember(Symbol symbol)
+ internal static Symbol GetAttributedMember(Symbol symbol)
{
for (; (object)symbol != null; symbol = symbol.ContainingSymbol)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs
index 966fe7bd991f5..557d1880d333b 100644
--- a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs
@@ -1396,7 +1396,7 @@ other is not (BoundDagNonNullTest or BoundDagExplicitNullTest) &&
// We should've skipped all type evaluations at this point.
case (BoundDagTypeEvaluation, _):
case (_, BoundDagTypeEvaluation):
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
// If we have found two identical evaluations as the source (possibly null), inputs can be considered related.
case var (s1, s2) when s1 == s2:
@@ -1868,7 +1868,7 @@ public StateForCase(
public override bool Equals(object? obj)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public bool Equals(StateForCase other)
@@ -1919,7 +1919,7 @@ public abstract void Filter(
out Tests whenTrue,
out Tests whenFalse,
ref bool foundExplicitNullTest);
- public virtual BoundDagTest ComputeSelectedTest() => throw ExceptionUtilities.Unreachable;
+ public virtual BoundDagTest ComputeSelectedTest() => throw ExceptionUtilities.Unreachable();
public virtual Tests RemoveEvaluation(BoundDagEvaluation e) => this;
///
/// Rewrite nested length tests in slice subpatterns to check the top-level length property instead.
diff --git a/src/Compilers/CSharp/Portable/Binder/EarlyWellKnownAttributeBinder.cs b/src/Compilers/CSharp/Portable/Binder/EarlyWellKnownAttributeBinder.cs
index 675b9bbca890b..72b24057ce660 100644
--- a/src/Compilers/CSharp/Portable/Binder/EarlyWellKnownAttributeBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/EarlyWellKnownAttributeBinder.cs
@@ -81,6 +81,7 @@ internal static bool CanBeValidAttributeArgument(ExpressionSyntax node, Binder t
case SyntaxKind.NumericLiteralExpression:
case SyntaxKind.StringLiteralExpression:
case SyntaxKind.Utf8StringLiteralExpression:
+ case SyntaxKind.InterpolatedStringExpression:
case SyntaxKind.CharacterLiteralExpression:
case SyntaxKind.TrueLiteralExpression:
case SyntaxKind.FalseLiteralExpression:
diff --git a/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs
index b66c7fc215caf..e1305e287f375 100644
--- a/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/EmbeddedStatementBinder.cs
@@ -73,7 +73,7 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
@@ -91,7 +91,7 @@ internal override ImmutableArray GetDeclaredLocalFunctionsF
return this.LocalFunctions;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/ExpressionListVariableBinder.cs b/src/Compilers/CSharp/Portable/Binder/ExpressionListVariableBinder.cs
index 600a75a445d68..0d6e275c6ec62 100644
--- a/src/Compilers/CSharp/Portable/Binder/ExpressionListVariableBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ExpressionListVariableBinder.cs
@@ -45,12 +45,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableBinder.cs b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableBinder.cs
index 4f16133aa41b9..f8671f97a6058 100644
--- a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableBinder.cs
@@ -38,12 +38,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/FixedStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/FixedStatementBinder.cs
index b88f7e725b1a2..12504562e5a8f 100644
--- a/src/Compilers/CSharp/Portable/Binder/FixedStatementBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/FixedStatementBinder.cs
@@ -64,12 +64,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
index e2e4b5945ab6d..520107e02a1c6 100644
--- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
@@ -1683,12 +1683,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/ForLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForLoopBinder.cs
index 11f68d5e373b6..89ac450e57f9c 100644
--- a/src/Compilers/CSharp/Portable/Binder/ForLoopBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ForLoopBinder.cs
@@ -136,12 +136,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs b/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs
index 784e159641413..23e8181eea18c 100644
--- a/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs
+++ b/src/Compilers/CSharp/Portable/Binder/PatternExplainer.cs
@@ -88,7 +88,7 @@ BoundWhenDecisionDagNode w when distance(w.WhenTrue) is var trueDist2 && distanc
n = w.WhenFalse;
break;
default:
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
@@ -555,7 +555,7 @@ private static string SampleValueString(IValueSet remainingValues, TypeSymbol ty
return $"> ({type.ToDisplayString()})uint.MaxValue";
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
private static string ValueString(ConstantValue value, TypeSymbol type, bool requireExactType)
diff --git a/src/Compilers/CSharp/Portable/Binder/ScriptLocalScopeBinder.cs b/src/Compilers/CSharp/Portable/Binder/ScriptLocalScopeBinder.cs
index e701dfdf57871..18877b0f0425f 100644
--- a/src/Compilers/CSharp/Portable/Binder/ScriptLocalScopeBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ScriptLocalScopeBinder.cs
@@ -41,12 +41,12 @@ internal override bool IsLabelsScopeBinder
internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
// Labels potentially shared across multiple ScriptLocalScopeBinder instances.
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/TypeConversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/TypeConversions.cs
index 1d87d01d8b315..9af64b2054d6d 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/TypeConversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/TypeConversions.cs
@@ -38,25 +38,25 @@ protected override ConversionsBase WithNullabilityCore(bool includeNullability)
public override Conversion GetMethodGroupDelegateConversion(BoundMethodGroup source, TypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo)
{
// Conversions involving method groups require a Binder.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public override Conversion GetMethodGroupFunctionPointerConversion(BoundMethodGroup source, FunctionPointerTypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo)
{
// Conversions involving method groups require a Binder.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public override Conversion GetStackAllocConversion(BoundStackAllocArrayCreation sourceExpression, TypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo)
{
// Conversions involving stackalloc expressions require a Binder.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
protected override Conversion GetInterpolatedStringConversion(BoundExpression source, TypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo)
{
// Conversions involving interpolated strings require a Binder.
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
protected override CSharpCompilation Compilation => null;
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorAnalysisResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorAnalysisResult.cs
index 64de9154fbc1a..46ded8b36bc3f 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorAnalysisResult.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorAnalysisResult.cs
@@ -38,13 +38,13 @@ public bool HasValue
public override bool Equals(object obj)
{
// implement if needed
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public override int GetHashCode()
{
// implement if needed
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public static BinaryOperatorAnalysisResult Applicable(BinaryOperatorSignature signature, Conversion leftConversion, Conversion rightConversion)
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs
index c61124e8316d6..def7395f182a8 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberAnalysisResult.cs
@@ -50,12 +50,12 @@ private MemberAnalysisResult(
public override bool Equals(object obj)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public override int GetHashCode()
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public Conversion ConversionForArg(int arg)
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
index 786c9ae505ad1..324afce093b87 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
@@ -2672,7 +2672,7 @@ public override BoundNode Visit(BoundNode node)
protected override BoundExpression VisitExpressionWithoutStackGuard(BoundExpression node)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
diff --git a/src/Compilers/CSharp/Portable/Binder/SimpleLocalScopeBinder.cs b/src/Compilers/CSharp/Portable/Binder/SimpleLocalScopeBinder.cs
index d7263e00a8711..119ac348b2ae9 100644
--- a/src/Compilers/CSharp/Portable/Binder/SimpleLocalScopeBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/SimpleLocalScopeBinder.cs
@@ -29,12 +29,12 @@ protected override ImmutableArray BuildLocals()
internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs b/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs
index a0c3a64df9f52..a7cfc5716f1cf 100644
--- a/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/SimpleProgramBinder.cs
@@ -91,7 +91,7 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
@@ -109,7 +109,7 @@ internal override ImmutableArray GetDeclaredLocalFunctionsF
return this.LocalFunctions;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs b/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs
index 5d193953c36c0..4538cd623a088 100644
--- a/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/SwitchBinder.cs
@@ -330,7 +330,7 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
@@ -340,7 +340,7 @@ internal override ImmutableArray GetDeclaredLocalFunctionsF
return this.LocalFunctions;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
index 4abc6cd60361e..fff7a1825be72 100644
--- a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
@@ -297,12 +297,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/WhileBinder.cs b/src/Compilers/CSharp/Portable/Binder/WhileBinder.cs
index d3b86d32cab06..1a3d40306d510 100644
--- a/src/Compilers/CSharp/Portable/Binder/WhileBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/WhileBinder.cs
@@ -73,12 +73,12 @@ internal override ImmutableArray GetDeclaredLocalsForScope(SyntaxNo
return this.Locals;
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override SyntaxNode ScopeDesignator
diff --git a/src/Compilers/CSharp/Portable/Binder/WithExternAndUsingAliasesBinder.cs b/src/Compilers/CSharp/Portable/Binder/WithExternAndUsingAliasesBinder.cs
index d1e64860628b2..93258d1b8b629 100644
--- a/src/Compilers/CSharp/Portable/Binder/WithExternAndUsingAliasesBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/WithExternAndUsingAliasesBinder.cs
@@ -92,7 +92,7 @@ internal bool IsUsingAlias(string name, bool callerIsSemanticModel, ConsList GetDeclaredLocalsForScope(SyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override ImmutableArray GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
internal override uint LocalScopeDepth => Binder.CurrentMethodScope;
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs
index 4b2c1a5311faf..f9325fb59db78 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs
@@ -134,7 +134,7 @@ internal partial class BoundValuePlaceholderBase
internal partial class BoundValuePlaceholder
{
- public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable;
+ public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable();
}
internal partial class BoundInterpolatedStringHandlerPlaceholder
@@ -149,7 +149,7 @@ internal partial class BoundDeconstructValuePlaceholder
internal partial class BoundTupleOperandPlaceholder
{
- public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable;
+ public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable();
}
internal partial class BoundAwaitableValuePlaceholder
@@ -169,7 +169,7 @@ internal partial class BoundObjectOrCollectionValuePlaceholder
internal partial class BoundImplicitIndexerValuePlaceholder
{
- public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable;
+ public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable();
}
internal partial class BoundListPatternReceiverPlaceholder
@@ -179,7 +179,7 @@ internal partial class BoundListPatternReceiverPlaceholder
internal partial class BoundListPatternIndexPlaceholder
{
- public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable;
+ public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable();
}
internal partial class BoundSlicePatternReceiverPlaceholder
@@ -189,7 +189,7 @@ internal partial class BoundSlicePatternReceiverPlaceholder
internal partial class BoundSlicePatternRangePlaceholder
{
- public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable;
+ public sealed override bool IsEquivalentToThisReference => throw ExceptionUtilities.Unreachable();
}
internal partial class BoundThisReference
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundInterpolatedStringArgumentPlaceholder.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundInterpolatedStringArgumentPlaceholder.cs
index 377d2e008b8b5..b1645affc7569 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundInterpolatedStringArgumentPlaceholder.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundInterpolatedStringArgumentPlaceholder.cs
@@ -10,6 +10,6 @@ internal partial class BoundInterpolatedStringArgumentPlaceholder
public const int TrailingConstructorValidityParameter = -2;
public const int UnspecifiedParameter = -3;
- public sealed override bool IsEquivalentToThisReference => throw Roslyn.Utilities.ExceptionUtilities.Unreachable;
+ public sealed override bool IsEquivalentToThisReference => throw Roslyn.Utilities.ExceptionUtilities.Unreachable();
}
}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodeExtensions.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundNodeExtensions.cs
index 52cc65546c387..de55f90b77792 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodeExtensions.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodeExtensions.cs
@@ -252,7 +252,7 @@ public static InterpolatedStringHandlerData GetInterpolatedStringHandlerData(thi
BoundBinaryOperator { InterpolatedStringHandlerData: { } d } => d,
BoundInterpolatedString { InterpolationData: { } d } => d,
BoundBinaryOperator or BoundInterpolatedString when !throwOnMissing => default,
- BoundBinaryOperator or BoundInterpolatedString => throw ExceptionUtilities.Unreachable,
+ BoundBinaryOperator or BoundInterpolatedString => throw ExceptionUtilities.Unreachable(),
_ => throw ExceptionUtilities.UnexpectedValue(e.Kind),
};
}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundStatementExtensions.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundStatementExtensions.cs
index b464d0ee79e00..df8bb05151434 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundStatementExtensions.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundStatementExtensions.cs
@@ -48,7 +48,7 @@ internal static void AssertIsLabeledStatementWithLabel(this BoundStatement node,
return;
}
}
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
default:
throw ExceptionUtilities.UnexpectedValue(node.Kind);
diff --git a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs
index b323c0ebe9479..f801e1d21d2cf 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/Formatting.cs
@@ -105,7 +105,7 @@ internal sealed partial class BoundPropertyGroup
{
public override object Display
{
- get { throw ExceptionUtilities.Unreachable; }
+ get { throw ExceptionUtilities.Unreachable(); }
}
}
@@ -137,7 +137,7 @@ internal partial class DeconstructionVariablePendingInference
{
public override object Display
{
- get { throw ExceptionUtilities.Unreachable; }
+ get { throw ExceptionUtilities.Unreachable(); }
}
}
diff --git a/src/Compilers/CSharp/Portable/BoundTree/NullabilityRewriter.cs b/src/Compilers/CSharp/Portable/BoundTree/NullabilityRewriter.cs
index db5389f0b60c1..1438c25004786 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/NullabilityRewriter.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/NullabilityRewriter.cs
@@ -121,7 +121,8 @@ Symbol remapLambda(BoundLambda boundLambda, LambdaSymbol lambda)
if (updatedDelegateType is null)
{
Debug.Assert(updatedContaining is object);
- updatedLambda = boundLambda.CreateLambdaSymbol(updatedContaining, lambda.ReturnTypeWithAnnotations, lambda.ParameterTypesWithAnnotations, lambda.ParameterRefKinds, lambda.RefKind);
+ var parameterEffectiveScopes = lambda.GetParameterEffectiveScopes();
+ updatedLambda = boundLambda.CreateLambdaSymbol(updatedContaining, lambda.ReturnTypeWithAnnotations, lambda.ParameterTypesWithAnnotations, lambda.ParameterRefKinds, parameterEffectiveScopes, lambda.RefKind);
}
else
{
diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
index 47c9754a7cc6c..f3848cc9c4c90 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
@@ -154,12 +154,14 @@ internal LambdaSymbol CreateLambdaSymbol(
TypeWithAnnotations returnType,
ImmutableArray parameterTypes,
ImmutableArray parameterRefKinds,
+ ImmutableArray parameterEffectiveScopes,
RefKind refKind)
=> UnboundLambda.Data.CreateLambdaSymbol(
containingSymbol,
returnType,
parameterTypes,
parameterRefKinds.IsDefault ? Enumerable.Repeat(RefKind.None, parameterTypes.Length).ToImmutableArray() : parameterRefKinds,
+ parameterEffectiveScopes,
refKind);
///
@@ -347,7 +349,7 @@ public static void GetReturnTypes(ArrayBuilder<(BoundReturnStatement, TypeWithAn
protected override BoundExpression VisitExpressionWithoutStackGuard(BoundExpression node)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
public override BoundNode? VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
@@ -611,7 +613,7 @@ private static TypeWithAnnotations DelegateReturnTypeWithAnnotations(MethodSymbo
}
var parameterRefKindsBuilder = ArrayBuilder.GetInstance(ParameterCount);
- var parameterScopesBuilder = ArrayBuilder.GetInstance(ParameterCount);
+ var parameterEffectiveScopesBuilder = ArrayBuilder.GetInstance(ParameterCount);
var parameterTypesBuilder = ArrayBuilder.GetInstance(ParameterCount);
bool getEffectiveScopeFromSymbol = false;
@@ -620,6 +622,7 @@ private static TypeWithAnnotations DelegateReturnTypeWithAnnotations(MethodSymbo
var refKind = RefKind(i);
var scope = DeclaredScope(i);
var type = ParameterTypeWithAnnotations(i);
+
if (scope == DeclarationScope.Unscoped &&
ParameterHelpers.IsRefScopedByDefault(Binder.UseUpdatedEscapeRules, refKind))
{
@@ -630,7 +633,7 @@ private static TypeWithAnnotations DelegateReturnTypeWithAnnotations(MethodSymbo
}
}
parameterRefKindsBuilder.Add(refKind);
- parameterScopesBuilder.Add(scope);
+ parameterEffectiveScopesBuilder.Add(scope);
parameterTypesBuilder.Add(type);
}
var parameterRefKinds = parameterRefKindsBuilder.ToImmutableAndFree();
@@ -670,20 +673,18 @@ private static TypeWithAnnotations DelegateReturnTypeWithAnnotations(MethodSymbo
for (int i = 0; i < ParameterCount; i++)
{
- if (DeclaredScope(i) == DeclarationScope.Unscoped && parameterScopesBuilder[i] == DeclarationScope.RefScoped && _unboundLambda.ParameterAttributes(i).Any())
+ if (DeclaredScope(i) == DeclarationScope.Unscoped && parameterEffectiveScopesBuilder[i] == DeclarationScope.RefScoped && _unboundLambda.ParameterAttributes(i).Any())
{
Debug.Assert(getEffectiveScopeFromSymbol);
- parameterScopesBuilder[i] = lambdaSymbol.Parameters[i].EffectiveScope;
+ parameterEffectiveScopesBuilder[i] = lambdaSymbol.Parameters[i].EffectiveScope;
}
else
{
- Debug.Assert(lambdaSymbol.Parameters[i].EffectiveScope == parameterScopesBuilder[i]);
+ Debug.Assert(lambdaSymbol.Parameters[i].EffectiveScope == parameterEffectiveScopesBuilder[i]);
}
}
}
- var parameterScopes = parameterScopesBuilder.ToImmutableAndFree();
-
if (!returnType.HasType)
{
// Binder.GetMethodGroupOrLambdaDelegateType() expects a non-null return type.
@@ -695,7 +696,7 @@ private static TypeWithAnnotations DelegateReturnTypeWithAnnotations(MethodSymbo
returnRefKind,
returnType,
parameterRefKinds,
- parameterScopes,
+ parameterEffectiveScopesBuilder.ToImmutableAndFree(),
parameterTypes);
LambdaSymbol createLambdaSymbol()
@@ -707,6 +708,7 @@ LambdaSymbol createLambdaSymbol()
_unboundLambda,
parameterTypes,
parameterRefKinds,
+ parameterEffectiveScopesBuilder.ToImmutable(),
refKind: default,
returnType: default);
}
@@ -749,7 +751,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType, bool inExpressionTr
}
else
{
- lambdaSymbol = CreateLambdaSymbol(Binder.ContainingMemberOrLambda, returnType, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, refKind);
+ lambdaSymbol = CreateLambdaSymbol(Binder.ContainingMemberOrLambda, returnType, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, cacheKey.ParameterEffectiveScopes, refKind);
lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, GetWithParametersBinder(lambdaSymbol, Binder), inExpressionTree ? BinderFlags.InExpressionTree : BinderFlags.None);
block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);
}
@@ -823,6 +825,7 @@ internal LambdaSymbol CreateLambdaSymbol(
TypeWithAnnotations returnType,
ImmutableArray parameterTypes,
ImmutableArray parameterRefKinds,
+ ImmutableArray parameterEffectiveScopes,
RefKind refKind)
=> new LambdaSymbol(
Binder,
@@ -831,6 +834,7 @@ internal LambdaSymbol CreateLambdaSymbol(
_unboundLambda,
parameterTypes,
parameterRefKinds,
+ parameterEffectiveScopes,
refKind,
returnType);
@@ -838,8 +842,10 @@ internal LambdaSymbol CreateLambdaSymbol(NamedTypeSymbol delegateType, Symbol co
{
var invokeMethod = DelegateInvokeMethod(delegateType);
var returnType = DelegateReturnTypeWithAnnotations(invokeMethod, out RefKind refKind);
- ReturnInferenceCacheKey.GetFields(delegateType, IsAsync, out var parameterTypes, out var parameterRefKinds, out _);
- return CreateLambdaSymbol(containingSymbol, returnType, parameterTypes, parameterRefKinds, refKind);
+ ReturnInferenceCacheKey.GetFields(delegateType, IsAsync, out var parameterTypes, out var parameterRefKinds,
+ out var parameterEffectiveScopes, out _);
+
+ return CreateLambdaSymbol(containingSymbol, returnType, parameterTypes, parameterRefKinds, parameterEffectiveScopes, refKind);
}
private void ValidateUnsafeParameters(BindingDiagnosticBag diagnostics, ImmutableArray targetParameterTypes)
@@ -870,10 +876,11 @@ private void ValidateUnsafeParameters(BindingDiagnosticBag diagnostics, Immutabl
private BoundLambda ReallyInferReturnType(
NamedTypeSymbol? delegateType,
ImmutableArray parameterTypes,
- ImmutableArray parameterRefKinds)
+ ImmutableArray parameterRefKinds,
+ ImmutableArray parameterEffectiveScopes)
{
bool hasExplicitReturnType = HasExplicitReturnType(out var refKind, out var returnType);
- (var lambdaSymbol, var block, var lambdaBodyBinder, var diagnostics) = BindWithParameterAndReturnType(parameterTypes, parameterRefKinds, returnType, refKind);
+ (var lambdaSymbol, var block, var lambdaBodyBinder, var diagnostics) = BindWithParameterAndReturnType(parameterTypes, parameterRefKinds, parameterEffectiveScopes, returnType, refKind);
InferredLambdaReturnType inferredReturnType;
if (hasExplicitReturnType)
{
@@ -928,6 +935,7 @@ private BoundLambda ReallyInferReturnType(
private (LambdaSymbol lambdaSymbol, BoundBlock block, ExecutableCodeBinder lambdaBodyBinder, BindingDiagnosticBag diagnostics) BindWithParameterAndReturnType(
ImmutableArray parameterTypes,
ImmutableArray parameterRefKinds,
+ ImmutableArray parameterEffectiveScopes,
TypeWithAnnotations returnType,
RefKind refKind)
{
@@ -936,6 +944,7 @@ private BoundLambda ReallyInferReturnType(
returnType,
parameterTypes,
parameterRefKinds,
+ parameterEffectiveScopes,
refKind);
var lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, GetWithParametersBinder(lambdaSymbol, Binder));
var block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);
@@ -950,7 +959,7 @@ public BoundLambda BindForReturnTypeInference(NamedTypeSymbol delegateType)
BoundLambda? result;
if (!_returnInferenceCache!.TryGetValue(cacheKey, out result))
{
- result = ReallyInferReturnType(delegateType, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds);
+ result = ReallyInferReturnType(delegateType, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, cacheKey.ParameterEffectiveScopes);
result = ImmutableInterlocked.GetOrAdd(ref _returnInferenceCache, cacheKey, result);
}
@@ -964,16 +973,22 @@ private sealed class ReturnInferenceCacheKey
{
public readonly ImmutableArray ParameterTypes;
public readonly ImmutableArray ParameterRefKinds;
+ public readonly ImmutableArray ParameterEffectiveScopes;
public readonly NamedTypeSymbol? TaskLikeReturnTypeOpt;
- public static readonly ReturnInferenceCacheKey Empty = new ReturnInferenceCacheKey(ImmutableArray.Empty, ImmutableArray.Empty, null);
+ public static readonly ReturnInferenceCacheKey Empty = new ReturnInferenceCacheKey(ImmutableArray.Empty, ImmutableArray.Empty,
+ parameterEffectiveScopes: default, taskLikeReturnTypeOpt: null);
- private ReturnInferenceCacheKey(ImmutableArray parameterTypes, ImmutableArray parameterRefKinds, NamedTypeSymbol? taskLikeReturnTypeOpt)
+ private ReturnInferenceCacheKey(ImmutableArray parameterTypes, ImmutableArray parameterRefKinds,
+ ImmutableArray parameterEffectiveScopes, NamedTypeSymbol? taskLikeReturnTypeOpt)
{
Debug.Assert(parameterTypes.Length == parameterRefKinds.Length);
+ Debug.Assert(parameterEffectiveScopes.IsDefault || parameterTypes.Length == parameterEffectiveScopes.Length);
Debug.Assert(taskLikeReturnTypeOpt is null || ((object)taskLikeReturnTypeOpt == taskLikeReturnTypeOpt.ConstructedFrom && taskLikeReturnTypeOpt.IsCustomTaskType(out var builderArgument)));
+
this.ParameterTypes = parameterTypes;
this.ParameterRefKinds = parameterRefKinds;
+ this.ParameterEffectiveScopes = parameterEffectiveScopes;
this.TaskLikeReturnTypeOpt = taskLikeReturnTypeOpt;
}
@@ -1002,7 +1017,12 @@ public override bool Equals(object? obj)
}
}
- return true;
+ if (this.ParameterEffectiveScopes.IsDefault || other.ParameterEffectiveScopes.IsDefault)
+ {
+ return this.ParameterEffectiveScopes.IsDefault == other.ParameterEffectiveScopes.IsDefault;
+ }
+
+ return this.ParameterEffectiveScopes.SequenceEqual(other.ParameterEffectiveScopes);
}
public override int GetHashCode()
@@ -1017,12 +1037,14 @@ public override int GetHashCode()
public static ReturnInferenceCacheKey Create(NamedTypeSymbol? delegateType, bool isAsync)
{
- GetFields(delegateType, isAsync, out var parameterTypes, out var parameterRefKinds, out var taskLikeReturnTypeOpt);
+ GetFields(delegateType, isAsync, out var parameterTypes, out var parameterRefKinds,
+ out var parameterEffectiveScopes, out var taskLikeReturnTypeOpt);
+
if (parameterTypes.IsEmpty && parameterRefKinds.IsEmpty && taskLikeReturnTypeOpt is null)
{
return Empty;
}
- return new ReturnInferenceCacheKey(parameterTypes, parameterRefKinds, taskLikeReturnTypeOpt);
+ return new ReturnInferenceCacheKey(parameterTypes, parameterRefKinds, parameterEffectiveScopes, taskLikeReturnTypeOpt);
}
public static void GetFields(
@@ -1030,12 +1052,14 @@ public static void GetFields(
bool isAsync,
out ImmutableArray parameterTypes,
out ImmutableArray parameterRefKinds,
+ out ImmutableArray parameterEffectiveScopes,
out NamedTypeSymbol? taskLikeReturnTypeOpt)
{
// delegateType or DelegateInvokeMethod can be null in cases of malformed delegates
// in such case we would want something trivial with no parameters
parameterTypes = ImmutableArray.Empty;
parameterRefKinds = ImmutableArray.Empty;
+ parameterEffectiveScopes = default;
taskLikeReturnTypeOpt = null;
MethodSymbol? invoke = DelegateInvokeMethod(delegateType);
if (invoke is not null)
@@ -1054,6 +1078,7 @@ public static void GetFields(
parameterTypes = typesBuilder.ToImmutableAndFree();
parameterRefKinds = refKindsBuilder.ToImmutableAndFree();
+ parameterEffectiveScopes = invoke.GetParameterEffectiveScopes();
}
if (isAsync)
@@ -1120,16 +1145,19 @@ private BoundLambda ReallyBindForErrorRecovery()
return
GuessBestBoundLambda(_bindingCache!)
?? rebind(GuessBestBoundLambda(_returnInferenceCache!))
- ?? rebind(ReallyInferReturnType(delegateType: null, ImmutableArray.Empty, ImmutableArray.Empty));
+ ?? rebind(ReallyInferReturnType(delegateType: null, ImmutableArray.Empty, ImmutableArray.Empty, parameterEffectiveScopes: default));
// Rebind a lambda to push target conversions through the return/result expressions
[return: NotNullIfNotNull("lambda")] BoundLambda? rebind(BoundLambda? lambda)
{
if (lambda is null)
return null;
+
var delegateType = (NamedTypeSymbol?)lambda.Type;
- ReturnInferenceCacheKey.GetFields(delegateType, IsAsync, out var parameterTypes, out var parameterRefKinds, out _);
- return ReallyBindForErrorRecovery(delegateType, lambda.InferredReturnType, parameterTypes, parameterRefKinds);
+ ReturnInferenceCacheKey.GetFields(delegateType, IsAsync, out var parameterTypes, out var parameterRefKinds,
+ out var parameterEffectiveScopes, taskLikeReturnTypeOpt: out _);
+
+ return ReallyBindForErrorRecovery(delegateType, lambda.InferredReturnType, parameterTypes, parameterRefKinds, parameterEffectiveScopes);
}
}
@@ -1137,7 +1165,8 @@ private BoundLambda ReallyBindForErrorRecovery(
NamedTypeSymbol? delegateType,
InferredLambdaReturnType inferredReturnType,
ImmutableArray parameterTypes,
- ImmutableArray parameterRefKinds)
+ ImmutableArray parameterRefKinds,
+ ImmutableArray parameterEffectiveScopes)
{
var returnType = inferredReturnType.TypeWithAnnotations;
var refKind = inferredReturnType.RefKind;
@@ -1156,7 +1185,7 @@ private BoundLambda ReallyBindForErrorRecovery(
}
}
- (var lambdaSymbol, var block, var lambdaBodyBinder, var diagnostics) = BindWithParameterAndReturnType(parameterTypes, parameterRefKinds, returnType, refKind);
+ (_, var block, var lambdaBodyBinder, var diagnostics) = BindWithParameterAndReturnType(parameterTypes, parameterRefKinds, parameterEffectiveScopes, returnType, refKind);
return new BoundLambda(
_unboundLambda.Syntax,
_unboundLambda,
diff --git a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs
index 4bd6f77e53aaf..9032d4d2572da 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs
+++ b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs
@@ -63,6 +63,12 @@ internal BoundExpression SetInferredTypeWithAnnotations(TypeWithAnnotations type
this.Syntax;
Binder.CheckRestrictedTypeInAsyncMethod(localSymbol.ContainingSymbol, type.Type, diagnosticsOpt, typeOrDesignationSyntax);
+
+ if (localSymbol.Scope == DeclarationScope.ValueScoped && !type.Type.IsErrorTypeOrRefLikeType())
+ {
+ diagnosticsOpt.Add(ErrorCode.ERR_ScopedRefAndRefStructOnly,
+ (typeOrDesignationSyntax is TypeSyntax typeSyntax ? typeSyntax.SkipScoped(out _).SkipRef(out _) : typeOrDesignationSyntax).Location);
+ }
}
}
@@ -120,7 +126,7 @@ private void ReportInferenceFailure(BindingDiagnosticBag diagnostics)
designation = (SingleVariableDesignationSyntax)this.Syntax;
break;
default:
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
Binder.Error(
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index dec462da992d5..616853f44bc14 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -985,7 +985,7 @@
Cannot call an abstract base member: '{0}'
- A property or indexer may not be passed as an out or ref parameter
+ A non ref-returning property or indexer may not be used as an out or ref value
Cannot take the address of, get the size of, or declare a pointer to a managed type ('{0}')
@@ -5920,6 +5920,15 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
This ref-assigns a value that has a narrower escape scope than the target.
+
+ Cannot ref-assign '{1}' to '{0}' because '{1}' has a wider value escape scope than '{0}' allowing assignment through '{0}' of values with narrower escapes scopes than '{1}'.
+
+
+ This ref-assigns '{1}' to '{0}' but '{1}' has a wider value escape scope than '{0}' allowing assignment through '{0}' of values with narrower escapes scopes than '{1}'.
+
+
+ This ref-assigns a value that has a wider value escape scope than the target allowing assignment through the target of values with narrower escapes scopes.
+
enum generic type constraints
@@ -7367,4 +7376,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
'readonly' is not supported as a parameter modifier. Did you mean 'in'?
+
+ The 'scoped' modifier cannot be used with discard.
+
+
+ A deconstruction variable cannot be declared as a ref local
+
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs
index f584f98d56624..a893bcf3c9c5f 100644
--- a/src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs
+++ b/src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs
@@ -329,7 +329,7 @@ private void EmitDelegateCreation(BoundExpression node, BoundExpression receiver
{
if (receiver is not BoundTypeExpression { Type: { TypeKind: TypeKind.TypeParameter } })
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
_builder.EmitOpCode(ILOpCode.Constrained);
diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
index 4efe4e8cada06..a83e4b624bb2f 100644
--- a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
+++ b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
@@ -48,7 +48,9 @@ private void EmitExpression(BoundExpression expression, bool used)
return;
}
- if ((object)expression.Type == null || expression.Type.SpecialType != SpecialType.System_Decimal)
+ if ((object)expression.Type == null ||
+ (expression.Type.SpecialType != SpecialType.System_Decimal &&
+ !expression.Type.IsNullableType()))
{
EmitConstantExpression(expression.Type, constantValue, used, expression.Syntax);
return;
@@ -1552,7 +1554,7 @@ private void EmitStaticCallExpression(BoundCall call, UseKind useKind)
{
if (receiver is not BoundTypeExpression { Type: { TypeKind: TypeKind.TypeParameter } })
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
_builder.EmitOpCode(ILOpCode.Constrained);
@@ -3562,7 +3564,7 @@ private void EmitLoadFunction(BoundFunctionPointerLoad load, bool used)
{
if (load.ConstrainedToTypeOpt is not { TypeKind: TypeKind.TypeParameter })
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
_builder.EmitOpCode(ILOpCode.Constrained);
diff --git a/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs b/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs
index 2eeabc2182d66..d23a4ca17d506 100644
--- a/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs
+++ b/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs
@@ -534,7 +534,7 @@ private BoundExpression VisitExpressionCoreWithStackGuard(BoundExpression node,
protected override BoundExpression VisitExpressionWithoutStackGuard(BoundExpression node)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
private void PushEvalStack(BoundExpression result, ExprContext context)
@@ -2114,7 +2114,7 @@ public override BoundNode VisitCall(BoundCall node)
}
else if (receiverOpt is not null)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
@@ -2261,13 +2261,13 @@ public override RefKind RefKind
/// Compiler should always be synthesizing locals with correct escape semantics.
/// Checking escape scopes is not valid here.
///
- internal override uint ValEscapeScope => throw ExceptionUtilities.Unreachable;
+ internal override uint ValEscapeScope => throw ExceptionUtilities.Unreachable();
///
/// Compiler should always be synthesizing locals with correct escape semantics.
/// Checking escape scopes is not valid here.
///
- internal override uint RefEscapeScope => throw ExceptionUtilities.Unreachable;
+ internal override uint RefEscapeScope => throw ExceptionUtilities.Unreachable();
internal override DeclarationScope Scope => DeclarationScope.Unscoped;
}
diff --git a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs
index 034a0f560e022..ae1c48ddba022 100644
--- a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs
+++ b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs
@@ -106,7 +106,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
bool embedAllSourceFiles = false;
bool resourcesOrModulesSpecified = false;
Encoding? codepage = null;
- var checksumAlgorithm = SourceHashAlgorithmUtils.DefaultContentHashAlgorithm;
+ var checksumAlgorithm = SourceHashAlgorithms.Default;
var defines = ArrayBuilder.GetInstance();
List metadataReferences = new List();
List analyzers = new List();
diff --git a/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs
index c6b787d323405..83583bdb01dd3 100644
--- a/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/AttributeSemanticModel.cs
@@ -16,40 +16,38 @@ namespace Microsoft.CodeAnalysis.CSharp
internal sealed class AttributeSemanticModel : MemberSemanticModel
{
private readonly AliasSymbol _aliasOpt;
+ private readonly Symbol? _attributeTarget;
- private AttributeSemanticModel(
+ internal AttributeSemanticModel(
AttributeSyntax syntax,
NamedTypeSymbol attributeType,
+ Symbol? attributeTarget,
AliasSymbol aliasOpt,
Binder rootBinder,
- SyntaxTreeSemanticModel? containingSemanticModelOpt = null,
- SyntaxTreeSemanticModel? parentSemanticModelOpt = null,
- ImmutableDictionary? parentRemappedSymbolsOpt = null,
- int speculatedPosition = 0)
- : base(syntax, attributeType, new ExecutableCodeBinder(syntax, rootBinder.ContainingMember(), rootBinder), containingSemanticModelOpt, parentSemanticModelOpt, snapshotManagerOpt: null, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt, speculatedPosition)
+ PublicSemanticModel containingPublicSemanticModel,
+ ImmutableDictionary? parentRemappedSymbolsOpt = null)
+ : base(syntax, attributeType, new ExecutableCodeBinder(syntax, rootBinder.ContainingMember(), rootBinder), containingPublicSemanticModel, parentRemappedSymbolsOpt)
{
Debug.Assert(syntax != null);
_aliasOpt = aliasOpt;
+ _attributeTarget = attributeTarget;
}
///
/// Creates an AttributeSemanticModel that allows asking semantic questions about an attribute node.
///
- public static AttributeSemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Symbol? attributeTarget, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt)
+ public static AttributeSemanticModel Create(PublicSemanticModel containingSemanticModel, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Symbol? attributeTarget, Binder rootBinder, ImmutableDictionary? parentRemappedSymbolsOpt)
{
rootBinder = attributeTarget is null ? rootBinder : new ContextualAttributeBinder(rootBinder, attributeTarget);
- return new AttributeSemanticModel(syntax, attributeType, aliasOpt, rootBinder, containingSemanticModel, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt);
+ return new AttributeSemanticModel(syntax, attributeType, attributeTarget, aliasOpt, rootBinder, containingSemanticModel, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt);
}
///
/// Creates a speculative AttributeSemanticModel that allows asking semantic questions about an attribute node that did not appear in the original source code.
///
- public static AttributeSemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt, int position)
+ public static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt, int position)
{
- Debug.Assert(parentSemanticModel != null);
- Debug.Assert(rootBinder != null);
- Debug.Assert(rootBinder.IsSemanticModelBinder);
- return new AttributeSemanticModel(syntax, attributeType, aliasOpt, rootBinder, parentSemanticModelOpt: parentSemanticModel, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt, speculatedPosition: position);
+ return new SpeculativeSemanticModelWithMemberModel(parentSemanticModel, position, syntax, attributeType, aliasOpt, rootBinder, parentRemappedSymbolsOpt);
}
private NamedTypeSymbol AttributeType
@@ -89,8 +87,7 @@ internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, BindingDi
if (node.Kind() == SyntaxKind.Attribute)
{
var attribute = (AttributeSyntax)node;
- // note: we should find the attributed member before binding the attribute as part of https://github.com/dotnet/roslyn/issues/53618
- return binder.BindAttribute(attribute, AttributeType, attributedMember: null, diagnostics);
+ return binder.BindAttribute(attribute, AttributeType, attributedMember: ContextualAttributeBinder.GetAttributedMember(_attributeTarget), diagnostics);
}
else if (SyntaxFacts.IsAttributeName(node))
{
@@ -128,43 +125,43 @@ internal static bool IsNullableAnalysisEnabledIn(CSharpCompilation compilation,
return compilation.IsNullableAnalysisEnabledIn(syntax);
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel? speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel? speculativeModel)
{
speculativeModel = null;
return false;
diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
index 1e581738b374a..73b5d50ee2c50 100644
--- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs
@@ -2505,10 +2505,12 @@ public virtual DataFlowAnalysis AnalyzeDataFlow(StatementSyntax statement)
public bool TryGetSpeculativeSemanticModelForMethodBody(int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(method);
- return TryGetSpeculativeSemanticModelForMethodBodyCore((SyntaxTreeSemanticModel)this, position, method, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelForMethodBodyCore((SyntaxTreeSemanticModel)this, position, method, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with a method body that did not appear in this source code.
@@ -2530,10 +2532,12 @@ public bool TryGetSpeculativeSemanticModelForMethodBody(int position, BaseMethod
public bool TryGetSpeculativeSemanticModelForMethodBody(int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(accessor);
- return TryGetSpeculativeSemanticModelForMethodBodyCore((SyntaxTreeSemanticModel)this, position, accessor, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelForMethodBodyCore((SyntaxTreeSemanticModel)this, position, accessor, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with a type syntax node that did not appear in
@@ -2557,10 +2561,12 @@ public bool TryGetSpeculativeSemanticModelForMethodBody(int position, AccessorDe
public bool TryGetSpeculativeSemanticModel(int position, TypeSyntax type, out SemanticModel speculativeModel, SpeculativeBindingOption bindingOption = SpeculativeBindingOption.BindAsExpression)
{
CheckModelAndSyntaxNodeToSpeculate(type);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, type, bindingOption, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, type, bindingOption, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, TypeSyntax type, SpeculativeBindingOption bindingOption, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, TypeSyntax type, SpeculativeBindingOption bindingOption, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with a statement that did not appear in
@@ -2581,10 +2587,12 @@ public bool TryGetSpeculativeSemanticModel(int position, TypeSyntax type, out Se
public bool TryGetSpeculativeSemanticModel(int position, StatementSyntax statement, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(statement);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, statement, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, statement, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with an initializer that did not appear in
@@ -2606,10 +2614,12 @@ public bool TryGetSpeculativeSemanticModel(int position, StatementSyntax stateme
public bool TryGetSpeculativeSemanticModel(int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(initializer);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, initializer, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, initializer, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with an expression body that did not appear in
@@ -2631,10 +2641,12 @@ public bool TryGetSpeculativeSemanticModel(int position, EqualsValueClauseSyntax
public bool TryGetSpeculativeSemanticModel(int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(expressionBody);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, expressionBody, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, expressionBody, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with a constructor initializer that did not appear in
@@ -2659,10 +2671,12 @@ public bool TryGetSpeculativeSemanticModel(int position, ArrowExpressionClauseSy
public bool TryGetSpeculativeSemanticModel(int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(constructorInitializer);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, constructorInitializer, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, constructorInitializer, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with a constructor initializer that did not appear in
@@ -2686,10 +2700,12 @@ public bool TryGetSpeculativeSemanticModel(int position, ConstructorInitializerS
public bool TryGetSpeculativeSemanticModel(int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(constructorInitializer);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, constructorInitializer, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, constructorInitializer, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with a cref that did not appear in
@@ -2714,10 +2730,12 @@ public bool TryGetSpeculativeSemanticModel(int position, PrimaryConstructorBaseT
public bool TryGetSpeculativeSemanticModel(int position, CrefSyntax crefSyntax, out SemanticModel speculativeModel)
{
CheckModelAndSyntaxNodeToSpeculate(crefSyntax);
- return TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, crefSyntax, out speculativeModel);
+ var result = TryGetSpeculativeSemanticModelCore((SyntaxTreeSemanticModel)this, position, crefSyntax, out PublicSemanticModel speculativeSyntaxTreeModel);
+ speculativeModel = speculativeSyntaxTreeModel;
+ return result;
}
- internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CrefSyntax crefSyntax, out SemanticModel speculativeModel);
+ internal abstract bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CrefSyntax crefSyntax, out PublicSemanticModel speculativeModel);
///
/// Get a SemanticModel object that is associated with an attribute that did not appear in
diff --git a/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
index 4ad1169eee1e5..c2ceb6136b97b 100644
--- a/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
@@ -23,14 +23,12 @@ internal sealed class InitializerSemanticModel : MemberSemanticModel
// create a SemanticModel for:
// (a) A true field initializer (field = value) of a named type (incl. Enums) OR
// (b) A parameter default value
- private InitializerSemanticModel(CSharpSyntaxNode syntax,
+ internal InitializerSemanticModel(CSharpSyntaxNode syntax,
Symbol symbol,
Binder rootBinder,
- SyntaxTreeSemanticModel containingSemanticModelOpt = null,
- SyntaxTreeSemanticModel parentSemanticModelOpt = null,
- ImmutableDictionary parentRemappedSymbolsOpt = null,
- int speculatedPosition = 0) :
- base(syntax, symbol, rootBinder, containingSemanticModelOpt, parentSemanticModelOpt, snapshotManagerOpt: null, parentRemappedSymbolsOpt, speculatedPosition)
+ PublicSemanticModel containingPublicSemanticModel,
+ ImmutableDictionary parentRemappedSymbolsOpt = null) :
+ base(syntax, symbol, rootBinder, containingPublicSemanticModel, parentRemappedSymbolsOpt)
{
Debug.Assert(!(syntax is ConstructorInitializerSyntax || syntax is PrimaryConstructorBaseTypeSyntax));
}
@@ -58,7 +56,7 @@ internal static InitializerSemanticModel Create(SyntaxTreeSemanticModel containi
///
/// Creates a SemanticModel for a parameter default value.
///
- internal static InitializerSemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, ParameterSyntax syntax, ParameterSymbol parameterSymbol, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt)
+ internal static InitializerSemanticModel Create(PublicSemanticModel containingSemanticModel, ParameterSyntax syntax, ParameterSymbol parameterSymbol, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt)
{
Debug.Assert(containingSemanticModel != null);
return new InitializerSemanticModel(syntax, parameterSymbol, rootBinder, containingSemanticModel, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt);
@@ -68,15 +66,9 @@ internal static InitializerSemanticModel Create(SyntaxTreeSemanticModel containi
/// Creates a speculative SemanticModel for an initializer node (field initializer, constructor initializer, or parameter default value)
/// that did not appear in the original source code.
///
- internal static InitializerSemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, Symbol owner, CSharpSyntaxNode syntax, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt, int position)
+ internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, Symbol owner, EqualsValueClauseSyntax syntax, Binder rootBinder, ImmutableDictionary parentRemappedSymbolsOpt, int position)
{
- Debug.Assert(parentSemanticModel != null);
- Debug.Assert(syntax != null);
- Debug.Assert(syntax.IsKind(SyntaxKind.EqualsValueClause));
- Debug.Assert(rootBinder != null);
- Debug.Assert(rootBinder.IsSemanticModelBinder);
-
- return new InitializerSemanticModel(syntax, owner, rootBinder, parentSemanticModelOpt: parentSemanticModel, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt, speculatedPosition: position);
+ return new SpeculativeSemanticModelWithMemberModel(parentSemanticModel, position, owner, syntax, rootBinder, parentRemappedSymbolsOpt);
}
protected internal override CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNode node)
@@ -208,7 +200,7 @@ private bool IsBindableInitializer(CSharpSyntaxNode node)
}
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel speculativeModel)
{
var binder = this.GetEnclosingBinder(position);
if (binder == null)
@@ -222,37 +214,37 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return true;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
index b789c52336355..8536e0ef6a327 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
@@ -283,7 +283,7 @@ public override BoundNode VisitConstructorMethodBody(BoundConstructorMethodBody
public override BoundNode VisitBinaryOperator(BoundBinaryOperator node)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
protected override bool ConvertInsufficientExecutionStackExceptionToCancelledByStackGuardException()
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs
index 0ecdcdc3f6b11..8d4ed467b8c22 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.SpeculativeMemberSemanticModel.cs
@@ -18,21 +18,26 @@ internal abstract partial class MemberSemanticModel
/// Allows asking semantic questions about a TypeSyntax (or its descendants) within a member, that did not appear in the original source code.
/// Typically, an instance is obtained by a call to SemanticModel.TryGetSpeculativeSemanticModel.
///
- private sealed class SpeculativeMemberSemanticModel : MemberSemanticModel
+ internal sealed class SpeculativeMemberSemanticModel : MemberSemanticModel
{
///
/// Creates a speculative SemanticModel for a TypeSyntax node at a position within an existing MemberSemanticModel.
///
- public SpeculativeMemberSemanticModel(SyntaxTreeSemanticModel parentSemanticModel, Symbol owner, TypeSyntax root, Binder rootBinder, NullableWalker.SnapshotManager snapshotManagerOpt, ImmutableDictionary parentRemappedSymbolsOpt, int position)
- : base(root, owner, rootBinder, containingSemanticModelOpt: null, parentSemanticModelOpt: parentSemanticModel, snapshotManagerOpt, parentRemappedSymbolsOpt, speculatedPosition: position)
+ public SpeculativeMemberSemanticModel(
+ PublicSemanticModel containingPublicSemanticModel,
+ Symbol owner,
+ TypeSyntax root,
+ Binder rootBinder,
+ ImmutableDictionary parentRemappedSymbolsOpt)
+ : base(root, owner, rootBinder, containingPublicSemanticModel: containingPublicSemanticModel, parentRemappedSymbolsOpt)
{
- Debug.Assert(parentSemanticModel is not null);
+ Debug.Assert(containingPublicSemanticModel is not null);
}
protected override NullableWalker.SnapshotManager GetSnapshotManager()
{
// In this override, current nullability state cannot influence anything of speculatively bound expressions.
- return _parentSnapshotManagerOpt;
+ return ((SpeculativeSemanticModelWithMemberModel)_containingPublicSemanticModel).ParentSnapshotManagerOpt;
}
protected override BoundNode RewriteNullableBoundNodesWithSnapshots(
@@ -54,42 +59,42 @@ protected override void AnalyzeBoundNodeNullability(BoundNode boundRoot, Binder
protected override bool IsNullableAnalysisEnabled()
{
- return _parentSemanticModelOpt.IsNullableAnalysisEnabledAtSpeculativePosition(OriginalPositionForSpeculation, Root);
+ return ((SyntaxTreeSemanticModel)_containingPublicSemanticModel.ParentModel).IsNullableAnalysisEnabledAtSpeculativePosition(_containingPublicSemanticModel.OriginalPositionForSpeculation, Root);
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel speculativeModel)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
index 15af834d57a1f..e46330abd63ad 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
@@ -20,6 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp
{
///
/// Binding info for expressions and statements that are part of a member declaration.
+ /// Instances of this class should not be exposed to external consumers.
///
internal abstract partial class MemberSemanticModel : CSharpSemanticModel
{
@@ -33,21 +34,10 @@ internal abstract partial class MemberSemanticModel : CSharpSemanticModel
private NullableWalker.SnapshotManager _lazySnapshotManager;
private ImmutableDictionary _lazyRemappedSymbols;
private readonly ImmutableDictionary _parentRemappedSymbolsOpt;
- ///
- /// Only used when this is a speculative semantic model.
- ///
- private readonly NullableWalker.SnapshotManager _parentSnapshotManagerOpt;
internal readonly Binder RootBinder;
- ///
- /// Field specific to a non-speculative MemberSemanticModel that must have a containing semantic model.
- ///
- private readonly SyntaxTreeSemanticModel _containingSemanticModelOpt;
-
- // Fields specific to a speculative MemberSemanticModel.
- private readonly SyntaxTreeSemanticModel _parentSemanticModelOpt;
- private readonly int _speculatedPosition;
+ private readonly PublicSemanticModel _containingPublicSemanticModel;
private readonly Lazy _operationFactory;
@@ -55,29 +45,19 @@ protected MemberSemanticModel(
CSharpSyntaxNode root,
Symbol memberSymbol,
Binder rootBinder,
- SyntaxTreeSemanticModel containingSemanticModelOpt,
- SyntaxTreeSemanticModel parentSemanticModelOpt,
- NullableWalker.SnapshotManager snapshotManagerOpt,
- ImmutableDictionary parentRemappedSymbolsOpt,
- int speculatedPosition)
+ PublicSemanticModel containingPublicSemanticModel,
+ ImmutableDictionary parentRemappedSymbolsOpt)
{
Debug.Assert(root != null);
Debug.Assert((object)memberSymbol != null);
- Debug.Assert(parentSemanticModelOpt == null ^ containingSemanticModelOpt == null);
- Debug.Assert(containingSemanticModelOpt == null || !containingSemanticModelOpt.IsSpeculativeSemanticModel);
- Debug.Assert(parentSemanticModelOpt == null || !parentSemanticModelOpt.IsSpeculativeSemanticModel, CSharpResources.ChainingSpeculativeModelIsNotSupported);
- Debug.Assert(snapshotManagerOpt == null || parentSemanticModelOpt != null);
+ Debug.Assert(containingPublicSemanticModel.IsSpeculativeSemanticModel == (containingPublicSemanticModel is SpeculativeSemanticModelWithMemberModel));
_root = root;
_memberSymbol = memberSymbol;
-
- this.RootBinder = rootBinder.WithAdditionalFlags(GetSemanticModelBinderFlags());
- _containingSemanticModelOpt = containingSemanticModelOpt;
- _parentSemanticModelOpt = parentSemanticModelOpt;
- _parentSnapshotManagerOpt = snapshotManagerOpt;
+ _containingPublicSemanticModel = containingPublicSemanticModel;
_parentRemappedSymbolsOpt = parentRemappedSymbolsOpt;
- _speculatedPosition = speculatedPosition;
+ this.RootBinder = rootBinder.WithAdditionalFlags(GetSemanticModelBinderFlags());
_operationFactory = new Lazy(() => new CSharpOperationFactory(this));
}
@@ -85,7 +65,7 @@ public override CSharpCompilation Compilation
{
get
{
- return (_containingSemanticModelOpt ?? _parentSemanticModelOpt).Compilation;
+ return _containingPublicSemanticModel.Compilation;
}
}
@@ -112,7 +92,15 @@ public sealed override bool IsSpeculativeSemanticModel
{
get
{
- return _parentSemanticModelOpt != null;
+ return _containingPublicSemanticModel.IsSpeculativeSemanticModel;
+ }
+ }
+
+ public sealed override bool IgnoresAccessibility
+ {
+ get
+ {
+ return _containingPublicSemanticModel.IgnoresAccessibility;
}
}
@@ -120,7 +108,9 @@ public sealed override int OriginalPositionForSpeculation
{
get
{
- return _speculatedPosition;
+ // This property is not meaningful for member semantic models.
+ // An external consumer should never be able to access them directly.
+ throw ExceptionUtilities.Unreachable();
}
}
@@ -128,15 +118,17 @@ public sealed override CSharpSemanticModel ParentModel
{
get
{
- return _parentSemanticModelOpt;
+ // This property is not meaningful for member semantic models.
+ // An external consumer should never be able to access them directly.
+ throw ExceptionUtilities.Unreachable();
}
}
- internal sealed override SemanticModel ContainingModelOrSelf
+ internal sealed override SemanticModel ContainingPublicModelOrSelf
{
get
{
- return _containingSemanticModelOpt ?? (SemanticModel)this;
+ return _containingPublicSemanticModel;
}
}
@@ -164,14 +156,14 @@ internal ImmutableDictionary GetRemappedSymbols()
return _lazyRemappedSymbols;
}
- internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, TypeSyntax type, SpeculativeBindingOption bindingOption, out SemanticModel speculativeModel)
+ internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, TypeSyntax type, SpeculativeBindingOption bindingOption, out PublicSemanticModel speculativeModel)
{
var expression = SyntaxFactory.GetStandaloneExpression(type);
var binder = this.GetSpeculativeBinder(position, expression, bindingOption);
if (binder != null)
{
- speculativeModel = new SpeculativeMemberSemanticModel(parentModel, _memberSymbol, type, binder, GetSnapshotManager(), GetRemappedSymbols(), position);
+ speculativeModel = new SpeculativeSemanticModelWithMemberModel(parentModel, position, _memberSymbol, type, binder, GetRemappedSymbols(), GetSnapshotManager());
return true;
}
@@ -179,7 +171,7 @@ internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSeman
return false;
}
- internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CrefSyntax crefSyntax, out SemanticModel speculativeModel)
+ internal sealed override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CrefSyntax crefSyntax, out PublicSemanticModel speculativeModel)
{
// crefs can never legally appear within members.
speculativeModel = null;
@@ -566,22 +558,22 @@ private static BoundNode GetLowerBoundNode(ImmutableArray boundNodes)
return boundNodes[boundNodes.Length - 1];
}
- public override ImmutableArray GetSyntaxDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ public sealed override ImmutableArray GetSyntaxDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotSupportedException();
}
- public override ImmutableArray GetDeclarationDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ public sealed override ImmutableArray GetDeclarationDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotSupportedException();
}
- public override ImmutableArray GetMethodBodyDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ public sealed override ImmutableArray GetMethodBodyDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotSupportedException();
}
- public override ImmutableArray GetDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ public sealed override ImmutableArray GetDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotSupportedException();
}
@@ -1953,13 +1945,14 @@ protected void EnsureNullabilityAnalysisPerformedIfNecessary()
// Not all speculative models are created with existing snapshots. Attributes,
// TypeSyntaxes, and MethodBodies do not depend on existing state in a member,
// and so the SnapshotManager can be null in these cases.
- if (_parentSnapshotManagerOpt is null || !isNullableAnalysisEnabled)
+ var parentSnapshotManagerOpt = ((SpeculativeSemanticModelWithMemberModel)_containingPublicSemanticModel).ParentSnapshotManagerOpt;
+ if (parentSnapshotManagerOpt is null || !isNullableAnalysisEnabled)
{
rewriteAndCache();
return;
}
- boundRoot = NullableWalker.AnalyzeAndRewriteSpeculation(_speculatedPosition, boundRoot, binder, _parentSnapshotManagerOpt, out var newSnapshots, ref remappedSymbols);
+ boundRoot = NullableWalker.AnalyzeAndRewriteSpeculation(_containingPublicSemanticModel.OriginalPositionForSpeculation, boundRoot, binder, parentSnapshotManagerOpt, out var newSnapshots, ref remappedSymbols);
GuardedAddBoundTreeForStandaloneSyntax(bindableRoot, boundRoot, newSnapshots, remappedSymbols);
}
else
@@ -2331,12 +2324,12 @@ internal override Symbol RemapSymbolIfNecessaryCore(Symbol symbol)
internal sealed override Func GetSyntaxNodesToAnalyzeFilter(SyntaxNode declaredNode, ISymbol declaredSymbol)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
- internal override bool ShouldSkipSyntaxNodeAnalysis(SyntaxNode node, ISymbol containingSymbol)
+ internal sealed override bool ShouldSkipSyntaxNodeAnalysis(SyntaxNode node, ISymbol containingSymbol)
{
- throw ExceptionUtilities.Unreachable;
+ throw ExceptionUtilities.Unreachable();
}
///
diff --git a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
index eba9d23ee4424..d7abb6cebe7c9 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
@@ -43,16 +43,13 @@ internal InitialState(
}
#nullable disable
- private MethodBodySemanticModel(
+ internal MethodBodySemanticModel(
MethodSymbol owner,
Binder rootBinder,
CSharpSyntaxNode syntax,
- SyntaxTreeSemanticModel containingSemanticModelOpt = null,
- SyntaxTreeSemanticModel parentSemanticModelOpt = null,
- NullableWalker.SnapshotManager snapshotManagerOpt = null,
- ImmutableDictionary parentRemappedSymbolsOpt = null,
- int speculatedPosition = 0)
- : base(syntax, owner, rootBinder, containingSemanticModelOpt, parentSemanticModelOpt, snapshotManagerOpt, parentRemappedSymbolsOpt, speculatedPosition)
+ PublicSemanticModel containingPublicSemanticModel,
+ ImmutableDictionary parentRemappedSymbolsOpt = null)
+ : base(syntax, owner, rootBinder, containingPublicSemanticModel, parentRemappedSymbolsOpt)
{
Debug.Assert((object)owner != null);
Debug.Assert(owner.Kind == SymbolKind.Method);
@@ -112,7 +109,7 @@ internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, BindingDi
///
/// Creates a speculative SemanticModel for a method body that did not appear in the original source code.
///
- internal static MethodBodySemanticModel CreateSpeculative(
+ internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(
SyntaxTreeSemanticModel parentSemanticModel,
MethodSymbol owner,
StatementSyntax syntax,
@@ -121,60 +118,52 @@ internal static MethodBodySemanticModel CreateSpeculative(
ImmutableDictionary parentRemappedSymbolsOpt,
int position)
{
- Debug.Assert(parentSemanticModel != null);
- Debug.Assert(syntax != null);
- Debug.Assert(rootBinder != null);
- Debug.Assert(rootBinder.IsSemanticModelBinder);
+ return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt, parentRemappedSymbolsOpt, position);
+ }
- return new MethodBodySemanticModel(owner, rootBinder, syntax, parentSemanticModelOpt: parentSemanticModel, snapshotManagerOpt: snapshotManagerOpt, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt, speculatedPosition: position);
+ private static SpeculativeSemanticModelWithMemberModel CreateSpeculativeForNode(
+ SyntaxTreeSemanticModel parentSemanticModel,
+ MethodSymbol owner,
+ CSharpSyntaxNode syntax,
+ Binder rootBinder,
+ NullableWalker.SnapshotManager snapshotManagerOpt,
+ ImmutableDictionary parentRemappedSymbolsOpt,
+ int position)
+ {
+ return new SpeculativeSemanticModelWithMemberModel(parentSemanticModel, position, owner, syntax, rootBinder, parentRemappedSymbolsOpt, snapshotManagerOpt);
}
///
/// Creates a speculative SemanticModel for an expression body that did not appear in the original source code.
///
- internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ArrowExpressionClauseSyntax syntax, Binder rootBinder, int position)
+ internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ArrowExpressionClauseSyntax syntax, Binder rootBinder, int position)
{
- Debug.Assert(parentSemanticModel != null);
- Debug.Assert(syntax != null);
- Debug.Assert(rootBinder != null);
- Debug.Assert(rootBinder.IsSemanticModelBinder);
-
- return new MethodBodySemanticModel(owner, rootBinder, syntax, parentSemanticModelOpt: parentSemanticModel, speculatedPosition: position);
+ return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: null, position);
}
///
/// Creates a speculative SemanticModel for a constructor initializer that did not appear in the original source code.
///
- internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ConstructorInitializerSyntax syntax, Binder rootBinder, int position)
+ internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ConstructorInitializerSyntax syntax, Binder rootBinder, int position)
{
- Debug.Assert(parentSemanticModel != null);
- Debug.Assert(syntax != null);
- Debug.Assert(rootBinder != null);
- Debug.Assert(rootBinder.IsSemanticModelBinder);
-
- return new MethodBodySemanticModel(owner, rootBinder, syntax, parentSemanticModelOpt: parentSemanticModel, speculatedPosition: position);
+ return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: null, position);
}
///
/// Creates a speculative SemanticModel for a constructor initializer that did not appear in the original source code.
///
- internal static MethodBodySemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, PrimaryConstructorBaseTypeSyntax syntax, Binder rootBinder, int position)
+ internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, PrimaryConstructorBaseTypeSyntax syntax, Binder rootBinder, int position)
{
- Debug.Assert(parentSemanticModel != null);
- Debug.Assert(syntax != null);
- Debug.Assert(rootBinder != null);
- Debug.Assert(rootBinder.IsSemanticModelBinder);
-
- return new MethodBodySemanticModel(owner, rootBinder, syntax, parentSemanticModelOpt: parentSemanticModel, speculatedPosition: position);
+ return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: null, position);
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel)
{
// CONSIDER: Do we want to ensure that speculated method and the original method have identical signatures?
return GetSpeculativeSemanticModelForMethodBody(parentModel, position, method.Body, out speculativeModel);
}
- private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
+ private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out PublicSemanticModel speculativeModel)
{
position = CheckAndAdjustPosition(position);
@@ -206,12 +195,12 @@ private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel pa
return true;
}
- internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel speculativeModel)
{
return GetSpeculativeSemanticModelForMethodBody(parentModel, position, accessor.Body, out speculativeModel);
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel speculativeModel)
{
position = CheckAndAdjustPosition(position);
@@ -229,7 +218,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return true;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel)
{
position = CheckAndAdjustPosition(position);
@@ -248,7 +237,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return true;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel)
{
if (MemberSymbol is MethodSymbol methodSymbol && methodSymbol.MethodKind == MethodKind.Constructor &&
Root.FindToken(position).Parent?.AncestorsAndSelf().OfType().FirstOrDefault()?.Parent == Root)
@@ -267,7 +256,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel)
{
if (MemberSymbol is SynthesizedRecordConstructor primaryCtor &&
primaryCtor.GetSyntax() is RecordDeclarationSyntax recordDecl)
@@ -290,7 +279,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
return false;
}
- internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out SemanticModel speculativeModel)
+ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel speculativeModel)
{
speculativeModel = null;
return false;
diff --git a/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs
new file mode 100644
index 0000000000000..a20b8224e5fd1
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/Compilation/PublicSemanticModel.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ ///
+ /// Instances of this can be exposed to external consumers.
+ /// Other types of are not designed for direct exposure
+ /// and their implementation might not be able to handle external requests properly.
+ ///
+ internal abstract partial class PublicSemanticModel : CSharpSemanticModel
+ {
+ protected AttributeSemanticModel CreateModelForAttribute(Binder enclosingBinder, AttributeSyntax attribute, MemberSemanticModel containingModel)
+ {
+ AliasSymbol aliasOpt;
+ var attributeType = (NamedTypeSymbol)enclosingBinder.BindType(attribute.Name, BindingDiagnosticBag.Discarded, out aliasOpt).Type;
+
+ // For attributes where a nameof could introduce some type parameters, we need to track the attribute target
+ Symbol? attributeTarget = getAttributeTarget(attribute.Parent?.Parent);
+
+ return AttributeSemanticModel.Create(
+ this,
+ attribute,
+ attributeType,
+ aliasOpt,
+ attributeTarget,
+ enclosingBinder.WithAdditionalFlags(BinderFlags.AttributeArgument),
+ containingModel?.GetRemappedSymbols());
+
+ Symbol? getAttributeTarget(SyntaxNode? targetSyntax)
+ {
+ return targetSyntax switch
+ {
+ BaseMethodDeclarationSyntax or
+ LocalFunctionStatementSyntax or
+ ParameterSyntax or
+ TypeParameterSyntax or
+ IndexerDeclarationSyntax or
+ AccessorDeclarationSyntax or
+ DelegateDeclarationSyntax => GetDeclaredSymbolForNode(targetSyntax).GetSymbol(),
+ AnonymousFunctionExpressionSyntax anonymousFunction => GetSymbolInfo(anonymousFunction).Symbol.GetSymbol(),
+ _ => null
+ };
+ }
+ }
+
+ internal sealed override SemanticModel ContainingPublicModelOrSelf => this;
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/Compilation/SpeculativeSemanticModelWithMemberModel.cs b/src/Compilers/CSharp/Portable/Compilation/SpeculativeSemanticModelWithMemberModel.cs
new file mode 100644
index 0000000000000..2060d512bef7b
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/Compilation/SpeculativeSemanticModelWithMemberModel.cs
@@ -0,0 +1,566 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Threading;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ ///
+ /// Instances of this type represent user-facing speculative semantic models that are backed by
+ /// internal .
+ ///
+ internal sealed class SpeculativeSemanticModelWithMemberModel : PublicSemanticModel
+ {
+ private readonly SyntaxTreeSemanticModel _parentSemanticModel;
+ private readonly int _position;
+ private readonly NullableWalker.SnapshotManager? _parentSnapshotManagerOpt;
+ private readonly MemberSemanticModel _memberModel;
+ private ImmutableDictionary _childMemberModels = ImmutableDictionary.Empty;
+
+ private SpeculativeSemanticModelWithMemberModel(
+ SyntaxTreeSemanticModel parentSemanticModel,
+ int position,
+ NullableWalker.SnapshotManager? snapshotManagerOpt)
+ {
+ Debug.Assert(parentSemanticModel is not null);
+
+ _parentSemanticModel = parentSemanticModel;
+ _position = position;
+ _parentSnapshotManagerOpt = snapshotManagerOpt;
+ _memberModel = null!;
+ }
+
+ public SpeculativeSemanticModelWithMemberModel(
+ SyntaxTreeSemanticModel parentSemanticModel,
+ int position,
+ AttributeSyntax syntax,
+ NamedTypeSymbol attributeType,
+ AliasSymbol aliasOpt,
+ Binder rootBinder,
+ ImmutableDictionary? parentRemappedSymbolsOpt)
+ : this(parentSemanticModel, position, snapshotManagerOpt: null)
+ {
+ Debug.Assert(syntax != null);
+ Debug.Assert(rootBinder != null);
+ Debug.Assert(rootBinder.IsSemanticModelBinder);
+
+ _memberModel = new AttributeSemanticModel(syntax, attributeType, getAttributeTargetFromPosition(position, parentSemanticModel), aliasOpt, rootBinder, containingPublicSemanticModel: this, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt);
+
+ static Symbol? getAttributeTargetFromPosition(int position, SyntaxTreeSemanticModel model)
+ {
+ var attributedNode = model.SyntaxTree.GetRoot().FindToken(position).Parent;
+ attributedNode = attributedNode?.FirstAncestorOrSelf()?.Parent;
+
+ if (attributedNode is not null)
+ {
+ return model.GetDeclaredSymbolForNode(attributedNode).GetSymbol();
+ }
+
+ return null;
+ }
+ }
+
+ public SpeculativeSemanticModelWithMemberModel(
+ SyntaxTreeSemanticModel parentSemanticModel,
+ int position,
+ Symbol owner,
+ EqualsValueClauseSyntax syntax,
+ Binder rootBinder,
+ ImmutableDictionary? parentRemappedSymbolsOpt)
+ : this(parentSemanticModel, position, snapshotManagerOpt: null)
+ {
+ Debug.Assert(syntax != null);
+ Debug.Assert(rootBinder != null);
+ Debug.Assert(rootBinder.IsSemanticModelBinder);
+
+ _memberModel = new InitializerSemanticModel(syntax, owner, rootBinder, containingPublicSemanticModel: this, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt);
+ }
+
+ public SpeculativeSemanticModelWithMemberModel(
+ SyntaxTreeSemanticModel parentModel,
+ int position,
+ Symbol owner,
+ TypeSyntax type,
+ Binder rootBinder,
+ ImmutableDictionary? parentRemappedSymbolsOpt,
+ NullableWalker.SnapshotManager? snapshotManagerOpt)
+ : this(parentModel, position, snapshotManagerOpt)
+ {
+ _memberModel = new MemberSemanticModel.SpeculativeMemberSemanticModel(this, owner, type, rootBinder, parentRemappedSymbolsOpt);
+ }
+
+ public SpeculativeSemanticModelWithMemberModel(
+ SyntaxTreeSemanticModel parentSemanticModel,
+ int position,
+ MethodSymbol owner,
+ CSharpSyntaxNode syntax,
+ Binder rootBinder,
+ ImmutableDictionary? parentRemappedSymbolsOpt,
+ NullableWalker.SnapshotManager? snapshotManagerOpt)
+ : this(parentSemanticModel, position, snapshotManagerOpt)
+ {
+ Debug.Assert(syntax != null);
+ Debug.Assert(rootBinder != null);
+ Debug.Assert(rootBinder.IsSemanticModelBinder);
+
+ _memberModel = new MethodBodySemanticModel(owner, rootBinder, syntax, containingPublicSemanticModel: this, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt);
+ }
+
+ internal NullableWalker.SnapshotManager? ParentSnapshotManagerOpt => _parentSnapshotManagerOpt;
+
+ public override bool IsSpeculativeSemanticModel => true;
+
+ public override int OriginalPositionForSpeculation => _position;
+
+ public override CSharpSemanticModel ParentModel => _parentSemanticModel;
+
+ public override CSharpCompilation Compilation => _parentSemanticModel.Compilation;
+
+ internal override CSharpSyntaxNode Root => _memberModel.Root;
+
+ public override SyntaxTree SyntaxTree => _memberModel.SyntaxTree;
+
+ public override bool IgnoresAccessibility => _parentSemanticModel.IgnoresAccessibility;
+
+ private MemberSemanticModel GetEnclosingMemberModel(int position)
+ {
+ AssertPositionAdjusted(position);
+ SyntaxNode? node = Root.FindTokenIncludingCrefAndNameAttributes(position).Parent;
+ return node is null ? _memberModel : GetEnclosingMemberModel(node);
+ }
+
+ private MemberSemanticModel GetEnclosingMemberModel(SyntaxNode node)
+ {
+ if (node.SyntaxTree != SyntaxTree)
+ {
+ return _memberModel;
+ }
+
+ var attributeOrParameter = node.FirstAncestorOrSelf(static n => n.Kind() is SyntaxKind.Attribute or SyntaxKind.Parameter);
+
+ if (attributeOrParameter is null ||
+ attributeOrParameter == Root ||
+ attributeOrParameter.Parent is null ||
+ !Root.Span.Contains(attributeOrParameter.Span))
+ {
+ return _memberModel;
+ }
+
+ MemberSemanticModel containing = GetEnclosingMemberModel(attributeOrParameter.Parent);
+
+ switch (attributeOrParameter)
+ {
+ case AttributeSyntax attribute:
+
+ return GetOrAddModelForAttribute(containing, attribute);
+
+ case ParameterSyntax paramDecl:
+
+ return GetOrAddModelForParameter(node, containing, paramDecl);
+
+ default:
+ ExceptionUtilities.UnexpectedValue(attributeOrParameter);
+ return containing;
+ }
+ }
+
+ private MemberSemanticModel GetOrAddModelForAttribute(MemberSemanticModel containing, AttributeSyntax attribute)
+ {
+ return ImmutableInterlocked.GetOrAdd(ref _childMemberModels, attribute,
+ (node, binderAndModel) => CreateModelForAttribute(binderAndModel.binder, (AttributeSyntax)node, binderAndModel.model),
+ (binder: containing.GetEnclosingBinder(attribute.SpanStart), model: containing));
+ }
+
+ private MemberSemanticModel GetOrAddModelForParameter(SyntaxNode node, MemberSemanticModel containing, ParameterSyntax paramDecl)
+ {
+ EqualsValueClauseSyntax? defaultValueSyntax = paramDecl.Default;
+
+ if (defaultValueSyntax != null && defaultValueSyntax.FullSpan.Contains(node.Span))
+ {
+ var parameterSymbol = containing.GetDeclaredSymbol(paramDecl).GetSymbol();
+ if ((object)parameterSymbol != null)
+ {
+ return ImmutableInterlocked.GetOrAdd(ref _childMemberModels, defaultValueSyntax,
+ (equalsValue, tuple) =>
+ InitializerSemanticModel.Create(
+ this,
+ tuple.paramDecl,
+ tuple.parameterSymbol,
+ tuple.containing.GetEnclosingBinder(tuple.paramDecl.SpanStart).
+ CreateBinderForParameterDefaultValue(tuple.parameterSymbol,
+ (EqualsValueClauseSyntax)equalsValue),
+ tuple.containing.GetRemappedSymbols()),
+ (compilation: this.Compilation,
+ paramDecl,
+ parameterSymbol,
+ containing)
+ );
+ }
+ }
+
+ return containing;
+ }
+
+ internal override MemberSemanticModel GetMemberModel(SyntaxNode node)
+ {
+ return GetEnclosingMemberModel(node).GetMemberModel(node);
+ }
+
+ public override Conversion ClassifyConversion(
+ ExpressionSyntax expression,
+ ITypeSymbol destination,
+ bool isExplicitInSource = false)
+ {
+ return GetEnclosingMemberModel(expression).ClassifyConversion(expression, destination, isExplicitInSource);
+ }
+
+ internal override Conversion ClassifyConversionForCast(
+ ExpressionSyntax expression,
+ TypeSymbol destination)
+ {
+ return GetEnclosingMemberModel(expression).ClassifyConversionForCast(expression, destination);
+ }
+
+ public override ImmutableArray GetSyntaxDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ImmutableArray GetDeclarationDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ImmutableArray GetMethodBodyDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ImmutableArray GetDiagnostics(TextSpan? span = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ throw new NotSupportedException();
+ }
+
+ public override INamespaceSymbol GetDeclaredSymbol(NamespaceDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override INamespaceSymbol GetDeclaredSymbol(FileScopedNamespaceDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override INamedTypeSymbol GetDeclaredSymbol(BaseTypeDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override INamedTypeSymbol GetDeclaredSymbol(DelegateDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IFieldSymbol GetDeclaredSymbol(EnumMemberDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override ISymbol GetDeclaredSymbol(LocalFunctionStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override ISymbol GetDeclaredSymbol(MemberDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IMethodSymbol GetDeclaredSymbol(CompilationUnitSyntax declarationSyntax, CancellationToken cancellationToken = default)
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IMethodSymbol GetDeclaredSymbol(BaseMethodDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override ISymbol GetDeclaredSymbol(BasePropertyDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IPropertySymbol GetDeclaredSymbol(PropertyDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IPropertySymbol GetDeclaredSymbol(IndexerDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IEventSymbol GetDeclaredSymbol(EventDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IMethodSymbol GetDeclaredSymbol(AccessorDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IMethodSymbol GetDeclaredSymbol(ArrowExpressionClauseSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override ISymbol GetDeclaredSymbol(VariableDeclaratorSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override ISymbol GetDeclaredSymbol(SingleVariableDesignationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ internal override LocalSymbol GetAdjustedLocalSymbol(SourceLocalSymbol local)
+ {
+ return _memberModel.GetAdjustedLocalSymbol(local);
+ }
+
+ public override ILabelSymbol GetDeclaredSymbol(LabeledStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override ILabelSymbol GetDeclaredSymbol(SwitchLabelSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IAliasSymbol GetDeclaredSymbol(UsingDirectiveSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IAliasSymbol GetDeclaredSymbol(ExternAliasDirectiveSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ public override IParameterSymbol GetDeclaredSymbol(ParameterSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbol(declarationSyntax, cancellationToken);
+ }
+
+ internal override ImmutableArray GetDeclaredSymbols(BaseFieldDeclarationSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declarationSyntax).GetDeclaredSymbols(declarationSyntax, cancellationToken);
+ }
+
+ public override ITypeParameterSymbol GetDeclaredSymbol(TypeParameterSyntax typeParameter, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(typeParameter).GetDeclaredSymbol(typeParameter, cancellationToken);
+ }
+
+ public override IRangeVariableSymbol GetDeclaredSymbol(JoinIntoClauseSyntax node, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetDeclaredSymbol(node, cancellationToken);
+ }
+
+ public override IRangeVariableSymbol GetDeclaredSymbol(QueryClauseSyntax queryClause, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(queryClause).GetDeclaredSymbol(queryClause, cancellationToken);
+ }
+
+ public override IRangeVariableSymbol GetDeclaredSymbol(QueryContinuationSyntax node, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetDeclaredSymbol(node, cancellationToken);
+ }
+
+ public override AwaitExpressionInfo GetAwaitExpressionInfo(AwaitExpressionSyntax node)
+ {
+ return GetEnclosingMemberModel(node).GetAwaitExpressionInfo(node);
+ }
+
+ public override ForEachStatementInfo GetForEachStatementInfo(ForEachStatementSyntax node)
+ {
+ return GetEnclosingMemberModel(node).GetForEachStatementInfo(node);
+ }
+
+ public override ForEachStatementInfo GetForEachStatementInfo(CommonForEachStatementSyntax node)
+ {
+ return GetEnclosingMemberModel(node).GetForEachStatementInfo(node);
+ }
+
+ public override DeconstructionInfo GetDeconstructionInfo(AssignmentExpressionSyntax node)
+ {
+ return GetEnclosingMemberModel(node).GetDeconstructionInfo(node);
+ }
+
+ public override DeconstructionInfo GetDeconstructionInfo(ForEachVariableStatementSyntax node)
+ {
+ return GetEnclosingMemberModel(node).GetDeconstructionInfo(node);
+ }
+
+ public override QueryClauseInfo GetQueryClauseInfo(QueryClauseSyntax node, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetQueryClauseInfo(node, cancellationToken);
+ }
+
+ public override IPropertySymbol GetDeclaredSymbol(AnonymousObjectMemberDeclaratorSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declaratorSyntax).GetDeclaredSymbol(declaratorSyntax, cancellationToken);
+ }
+
+ public override INamedTypeSymbol GetDeclaredSymbol(AnonymousObjectCreationExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declaratorSyntax).GetDeclaredSymbol(declaratorSyntax, cancellationToken);
+ }
+
+ public override INamedTypeSymbol GetDeclaredSymbol(TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declaratorSyntax).GetDeclaredSymbol(declaratorSyntax, cancellationToken);
+ }
+
+ public override ISymbol GetDeclaredSymbol(ArgumentSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(declaratorSyntax).GetDeclaredSymbol(declaratorSyntax, cancellationToken);
+ }
+
+ internal override IOperation? GetOperationWorker(CSharpSyntaxNode node, CancellationToken cancellationToken)
+ {
+ return GetEnclosingMemberModel(node).GetOperationWorker(node, cancellationToken);
+ }
+
+ internal override SymbolInfo GetSymbolInfoWorker(CSharpSyntaxNode node, SymbolInfoOptions options, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetSymbolInfoWorker(node, options, cancellationToken);
+ }
+
+ internal override CSharpTypeInfo GetTypeInfoWorker(CSharpSyntaxNode node, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetTypeInfoWorker(node, cancellationToken);
+ }
+
+ internal override ImmutableArray GetMemberGroupWorker(CSharpSyntaxNode node, SymbolInfoOptions options, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetMemberGroupWorker(node, options, cancellationToken);
+ }
+
+ internal override ImmutableArray GetIndexerGroupWorker(CSharpSyntaxNode node, SymbolInfoOptions options, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return GetEnclosingMemberModel(node).GetIndexerGroupWorker(node, options, cancellationToken);
+ }
+
+ internal override Optional