diff --git a/Directory.Build.rsp b/Directory.Build.rsp
index d2d2d1d2f4e8e..37bf61d3487f8 100644
--- a/Directory.Build.rsp
+++ b/Directory.Build.rsp
@@ -1 +1,2 @@
-# This file intentionally left blank to avoid accidental import during build.
+# Workaround for https://github.com/dotnet/sdk/issues/41791
+-p:_IsDisjointMSBuildVersion=false
diff --git a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs
index dedfa4b189a42..4413bf53ca539 100644
--- a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs
+++ b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs
@@ -6,7 +6,6 @@
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
-using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.CSharp.Simplification;
using Microsoft.CodeAnalysis.Options;
@@ -15,115 +14,87 @@ namespace Microsoft.CodeAnalysis.Diagnostics;
///
/// Provides C# analyzers a convenient access to editorconfig options with fallback to IDE default values.
///
-internal readonly struct CSharpAnalyzerOptionsProvider(IOptionsReader options, IdeAnalyzerOptions fallbackOptions)
+internal readonly struct CSharpAnalyzerOptionsProvider(IOptionsReader options)
{
- ///
- /// Document editorconfig options.
- ///
- private readonly IOptionsReader _options = options;
-
- ///
- /// Fallback options - the default options in Code Style layer.
- ///
- private readonly IdeAnalyzerOptions _fallbackOptions = fallbackOptions;
-
- public CSharpAnalyzerOptionsProvider(IOptionsReader options, AnalyzerOptions fallbackOptions)
- : this(options, fallbackOptions.GetIdeOptions())
- {
- }
+ private IOptionsReader Options => options;
// SimplifierOptions
- public CodeStyleOption2 VarForBuiltInTypes => GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes, FallbackSimplifierOptions.VarForBuiltInTypes);
- public CodeStyleOption2 VarWhenTypeIsApparent => GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent, FallbackSimplifierOptions.VarWhenTypeIsApparent);
- public CodeStyleOption2 VarElsewhere => GetOption(CSharpCodeStyleOptions.VarElsewhere, FallbackSimplifierOptions.VarElsewhere);
- public CodeStyleOption2 PreferSimpleDefaultExpression => GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression, FallbackSimplifierOptions.PreferSimpleDefaultExpression);
- public CodeStyleOption2 AllowEmbeddedStatementsOnSameLine => GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine, FallbackSimplifierOptions.AllowEmbeddedStatementsOnSameLine);
- public CodeStyleOption2 PreferThrowExpression => GetOption(CSharpCodeStyleOptions.PreferThrowExpression, FallbackSimplifierOptions.PreferThrowExpression);
- public CodeStyleOption2 PreferBraces => GetOption(CSharpCodeStyleOptions.PreferBraces, FallbackSimplifierOptions.PreferBraces);
+ public CodeStyleOption2 VarForBuiltInTypes => GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes);
+ public CodeStyleOption2 VarWhenTypeIsApparent => GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent);
+ public CodeStyleOption2 VarElsewhere => GetOption(CSharpCodeStyleOptions.VarElsewhere);
+ public CodeStyleOption2 PreferSimpleDefaultExpression => GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression);
+ public CodeStyleOption2 AllowEmbeddedStatementsOnSameLine => GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine);
+ public CodeStyleOption2 PreferThrowExpression => GetOption(CSharpCodeStyleOptions.PreferThrowExpression);
+ public CodeStyleOption2 PreferBraces => GetOption(CSharpCodeStyleOptions.PreferBraces);
internal CSharpSimplifierOptions GetSimplifierOptions()
- => new(_options, FallbackSimplifierOptions);
+ => new(options, fallbackOptions: null);
// SyntaxFormattingOptions
- public CodeStyleOption2 NamespaceDeclarations => GetOption(CSharpCodeStyleOptions.NamespaceDeclarations, FallbackSyntaxFormattingOptions.NamespaceDeclarations);
- public CodeStyleOption2 PreferTopLevelStatements => GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements, FallbackSyntaxFormattingOptions.PreferTopLevelStatements);
+ public CodeStyleOption2 NamespaceDeclarations => GetOption(CSharpCodeStyleOptions.NamespaceDeclarations);
+ public CodeStyleOption2 PreferTopLevelStatements => GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements);
// AddImportPlacementOptions
- public CodeStyleOption2 UsingDirectivePlacement => GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, FallbackAddImportPlacementOptions.UsingDirectivePlacement);
+ public CodeStyleOption2 UsingDirectivePlacement => GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement);
// CodeStyleOptions
- public CodeStyleOption2 ImplicitObjectCreationWhenTypeIsApparent => GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, FallbackCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent);
- public CodeStyleOption2 PreferNullCheckOverTypeCheck => GetOption(CSharpCodeStyleOptions.PreferNullCheckOverTypeCheck, FallbackCodeStyleOptions.PreferNullCheckOverTypeCheck);
- public CodeStyleOption2 AllowBlankLinesBetweenConsecutiveBraces => GetOption(CSharpCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces, FallbackCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces);
- public CodeStyleOption2 AllowBlankLineAfterColonInConstructorInitializer => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer, FallbackCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer);
- public CodeStyleOption2 AllowBlankLineAfterTokenInArrowExpressionClause => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterTokenInArrowExpressionClause, FallbackCodeStyleOptions.AllowBlankLineAfterTokenInArrowExpressionClause);
- public CodeStyleOption2 AllowBlankLineAfterTokenInConditionalExpression => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterTokenInConditionalExpression, FallbackCodeStyleOptions.AllowBlankLineAfterTokenInConditionalExpression);
- public CodeStyleOption2 PreferConditionalDelegateCall => GetOption(CSharpCodeStyleOptions.PreferConditionalDelegateCall, FallbackCodeStyleOptions.PreferConditionalDelegateCall);
- public CodeStyleOption2 PreferSwitchExpression => GetOption(CSharpCodeStyleOptions.PreferSwitchExpression, FallbackCodeStyleOptions.PreferSwitchExpression);
- public CodeStyleOption2 PreferPatternMatching => GetOption(CSharpCodeStyleOptions.PreferPatternMatching, FallbackCodeStyleOptions.PreferPatternMatching);
- public CodeStyleOption2 PreferPatternMatchingOverAsWithNullCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, FallbackCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck);
- public CodeStyleOption2 PreferPatternMatchingOverIsWithCastCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, FallbackCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck);
- public CodeStyleOption2 PreferNotPattern => GetOption(CSharpCodeStyleOptions.PreferNotPattern, FallbackCodeStyleOptions.PreferNotPattern);
- public CodeStyleOption2 PreferExtendedPropertyPattern => GetOption(CSharpCodeStyleOptions.PreferExtendedPropertyPattern, FallbackCodeStyleOptions.PreferExtendedPropertyPattern);
- public CodeStyleOption2 PreferInlinedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferInlinedVariableDeclaration, FallbackCodeStyleOptions.PreferInlinedVariableDeclaration);
- public CodeStyleOption2 PreferDeconstructedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferDeconstructedVariableDeclaration, FallbackCodeStyleOptions.PreferDeconstructedVariableDeclaration);
- public CodeStyleOption2 PreferIndexOperator => GetOption(CSharpCodeStyleOptions.PreferIndexOperator, FallbackCodeStyleOptions.PreferIndexOperator);
- public CodeStyleOption2 PreferRangeOperator => GetOption(CSharpCodeStyleOptions.PreferRangeOperator, FallbackCodeStyleOptions.PreferRangeOperator);
- public CodeStyleOption2 PreferUtf8StringLiterals => GetOption(CSharpCodeStyleOptions.PreferUtf8StringLiterals, FallbackCodeStyleOptions.PreferUtf8StringLiterals);
- public CodeStyleOption2 PreferredModifierOrder => GetOption(CSharpCodeStyleOptions.PreferredModifierOrder, FallbackCodeStyleOptions.PreferredModifierOrder);
- public CodeStyleOption2 PreferSimpleUsingStatement => GetOption(CSharpCodeStyleOptions.PreferSimpleUsingStatement, FallbackCodeStyleOptions.PreferSimpleUsingStatement);
- public CodeStyleOption2 PreferLocalOverAnonymousFunction => GetOption(CSharpCodeStyleOptions.PreferLocalOverAnonymousFunction, FallbackCodeStyleOptions.PreferLocalOverAnonymousFunction);
- public CodeStyleOption2 PreferTupleSwap => GetOption(CSharpCodeStyleOptions.PreferTupleSwap, FallbackCodeStyleOptions.PreferTupleSwap);
- public CodeStyleOption2 UnusedValueExpressionStatement => GetOption(CSharpCodeStyleOptions.UnusedValueExpressionStatement, FallbackCodeStyleOptions.UnusedValueExpressionStatement);
- public CodeStyleOption2 UnusedValueAssignment => GetOption(CSharpCodeStyleOptions.UnusedValueAssignment, FallbackCodeStyleOptions.UnusedValueAssignment);
- public CodeStyleOption2 PreferMethodGroupConversion => GetOption(CSharpCodeStyleOptions.PreferMethodGroupConversion, FallbackCodeStyleOptions.PreferMethodGroupConversion);
- public CodeStyleOption2 PreferPrimaryConstructors => GetOption(CSharpCodeStyleOptions.PreferPrimaryConstructors, FallbackCodeStyleOptions.PreferPrimaryConstructors);
- public CodeStyleOption2 PreferSystemThreadingLock => GetOption(CSharpCodeStyleOptions.PreferSystemThreadingLock, FallbackCodeStyleOptions.PreferSystemThreadingLock);
+ public CodeStyleOption2 ImplicitObjectCreationWhenTypeIsApparent => GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent);
+ public CodeStyleOption2 PreferNullCheckOverTypeCheck => GetOption(CSharpCodeStyleOptions.PreferNullCheckOverTypeCheck);
+ public CodeStyleOption2 AllowBlankLinesBetweenConsecutiveBraces => GetOption(CSharpCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces);
+ public CodeStyleOption2 AllowBlankLineAfterColonInConstructorInitializer => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer);
+ public CodeStyleOption2 AllowBlankLineAfterTokenInArrowExpressionClause => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterTokenInArrowExpressionClause);
+ public CodeStyleOption2 AllowBlankLineAfterTokenInConditionalExpression => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterTokenInConditionalExpression);
+ public CodeStyleOption2 PreferConditionalDelegateCall => GetOption(CSharpCodeStyleOptions.PreferConditionalDelegateCall);
+ public CodeStyleOption2 PreferSwitchExpression => GetOption(CSharpCodeStyleOptions.PreferSwitchExpression);
+ public CodeStyleOption2 PreferPatternMatching => GetOption(CSharpCodeStyleOptions.PreferPatternMatching);
+ public CodeStyleOption2 PreferPatternMatchingOverAsWithNullCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck);
+ public CodeStyleOption2 PreferPatternMatchingOverIsWithCastCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck);
+ public CodeStyleOption2 PreferNotPattern => GetOption(CSharpCodeStyleOptions.PreferNotPattern);
+ public CodeStyleOption2 PreferExtendedPropertyPattern => GetOption(CSharpCodeStyleOptions.PreferExtendedPropertyPattern);
+ public CodeStyleOption2 PreferInlinedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferInlinedVariableDeclaration);
+ public CodeStyleOption2 PreferDeconstructedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferDeconstructedVariableDeclaration);
+ public CodeStyleOption2 PreferIndexOperator => GetOption(CSharpCodeStyleOptions.PreferIndexOperator);
+ public CodeStyleOption2 PreferRangeOperator => GetOption(CSharpCodeStyleOptions.PreferRangeOperator);
+ public CodeStyleOption2 PreferUtf8StringLiterals => GetOption(CSharpCodeStyleOptions.PreferUtf8StringLiterals);
+ public CodeStyleOption2 PreferredModifierOrder => GetOption(CSharpCodeStyleOptions.PreferredModifierOrder);
+ public CodeStyleOption2 PreferSimpleUsingStatement => GetOption(CSharpCodeStyleOptions.PreferSimpleUsingStatement);
+ public CodeStyleOption2 PreferLocalOverAnonymousFunction => GetOption(CSharpCodeStyleOptions.PreferLocalOverAnonymousFunction);
+ public CodeStyleOption2 PreferTupleSwap => GetOption(CSharpCodeStyleOptions.PreferTupleSwap);
+ public CodeStyleOption2 UnusedValueExpressionStatement => GetOption(CSharpCodeStyleOptions.UnusedValueExpressionStatement);
+ public CodeStyleOption2 UnusedValueAssignment => GetOption(CSharpCodeStyleOptions.UnusedValueAssignment);
+ public CodeStyleOption2 PreferMethodGroupConversion => GetOption(CSharpCodeStyleOptions.PreferMethodGroupConversion);
+ public CodeStyleOption2 PreferPrimaryConstructors => GetOption(CSharpCodeStyleOptions.PreferPrimaryConstructors);
+ public CodeStyleOption2 PreferSystemThreadingLock => GetOption(CSharpCodeStyleOptions.PreferSystemThreadingLock);
// CodeGenerationOptions
internal CSharpCodeGenerationOptions GetCodeGenerationOptions()
- => new(_options, FallbackCodeGenerationOptions);
-
- public CodeStyleOption2 PreferExpressionBodiedLambdas => GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas, FallbackCodeStyleOptions.PreferExpressionBodiedLambdas);
- public CodeStyleOption2 PreferReadOnlyStruct => GetOption(CSharpCodeStyleOptions.PreferReadOnlyStruct, FallbackCodeStyleOptions.PreferReadOnlyStruct);
- public CodeStyleOption2 PreferReadOnlyStructMember => GetOption(CSharpCodeStyleOptions.PreferReadOnlyStructMember, FallbackCodeStyleOptions.PreferReadOnlyStructMember);
- public CodeStyleOption2 PreferStaticLocalFunction => GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction, FallbackCodeStyleOptions.PreferStaticLocalFunction);
- public CodeStyleOption2 PreferStaticAnonymousFunction => GetOption(CSharpCodeStyleOptions.PreferStaticAnonymousFunction, FallbackCodeStyleOptions.PreferStaticAnonymousFunction);
-
- private TValue GetOption(Option2 option, TValue defaultValue)
- => _options.GetOption(option, defaultValue);
-
- private CSharpIdeCodeStyleOptions FallbackCodeStyleOptions
- => (CSharpIdeCodeStyleOptions?)_fallbackOptions.CodeStyleOptions ?? CSharpIdeCodeStyleOptions.Default;
-
- private CSharpSimplifierOptions FallbackSimplifierOptions
- => (CSharpSimplifierOptions?)_fallbackOptions.CleanupOptions?.SimplifierOptions ?? CSharpSimplifierOptions.Default;
-
- private CSharpSyntaxFormattingOptions FallbackSyntaxFormattingOptions
- => (CSharpSyntaxFormattingOptions?)_fallbackOptions.CleanupOptions?.FormattingOptions ?? CSharpSyntaxFormattingOptions.Default;
+ => new(options, fallbackOptions: null);
- private AddImportPlacementOptions FallbackAddImportPlacementOptions
- => _fallbackOptions.CleanupOptions?.AddImportOptions ?? AddImportPlacementOptions.Default;
+ public CodeStyleOption2 PreferExpressionBodiedLambdas => GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas);
+ public CodeStyleOption2 PreferReadOnlyStruct => GetOption(CSharpCodeStyleOptions.PreferReadOnlyStruct);
+ public CodeStyleOption2 PreferReadOnlyStructMember => GetOption(CSharpCodeStyleOptions.PreferReadOnlyStructMember);
+ public CodeStyleOption2 PreferStaticLocalFunction => GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction);
+ public CodeStyleOption2 PreferStaticAnonymousFunction => GetOption(CSharpCodeStyleOptions.PreferStaticAnonymousFunction);
- private CSharpCodeGenerationOptions FallbackCodeGenerationOptions
- => (CSharpCodeGenerationOptions?)_fallbackOptions.GenerationOptions ?? CSharpCodeGenerationOptions.Default;
+ private TValue GetOption(Option2 option)
+ => options.GetOption(option);
public static explicit operator CSharpAnalyzerOptionsProvider(AnalyzerOptionsProvider provider)
- => new(provider.GetAnalyzerConfigOptions(), provider.GetFallbackOptions());
+ => new(provider.GetAnalyzerConfigOptions());
public static implicit operator AnalyzerOptionsProvider(CSharpAnalyzerOptionsProvider provider)
- => new(provider._options, LanguageNames.CSharp, provider._fallbackOptions);
+ => new(provider.Options, LanguageNames.CSharp);
}
internal static class CSharpAnalyzerOptionsProviders
{
public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this AnalyzerOptions options, SyntaxTree syntaxTree)
- => new(options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader(), options);
+ => new(options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader());
public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this SemanticModelAnalysisContext context)
=> GetCSharpAnalyzerOptions(context.Options, context.SemanticModel.SyntaxTree);
diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpCollectionExpressionRewriter.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpCollectionExpressionRewriter.cs
index 5de5853e93db8..4fbb6222312c9 100644
--- a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpCollectionExpressionRewriter.cs
+++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpCollectionExpressionRewriter.cs
@@ -50,8 +50,7 @@ public static async Task CreateCollectionExpressionA
#if CODE_STYLE
var formattingOptions = CSharpSyntaxFormattingOptions.Default;
#else
- var formattingOptions = (CSharpSyntaxFormattingOptions)await workspaceDocument.GetSyntaxFormattingOptionsAsync(
- fallbackOptions, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = (CSharpSyntaxFormattingOptions)await workspaceDocument.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
#endif
var indentationOptions = new IndentationOptions(formattingOptions);
diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs
index fab7a804b6b76..d81166a7aea57 100644
--- a/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs
+++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionExpression/CSharpUseCollectionExpressionForFluentCodeFixProvider.cs
@@ -150,8 +150,7 @@ static async Task> GetArgumentsAsync(
#if CODE_STYLE
var formattingOptions = SyntaxFormattingOptions.CommonDefaults;
#else
- var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(
- fallbackOptions, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
#endif
using var _ = ArrayBuilder.GetInstance(out var nodesAndTokens);
diff --git a/src/Analyzers/Core/Analyzers/AnalyzerOptionsProvider.cs b/src/Analyzers/Core/Analyzers/AnalyzerOptionsProvider.cs
index efa914b38a10b..9ff472e4bf746 100644
--- a/src/Analyzers/Core/Analyzers/AnalyzerOptionsProvider.cs
+++ b/src/Analyzers/Core/Analyzers/AnalyzerOptionsProvider.cs
@@ -2,118 +2,83 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.CodeStyle;
-using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
namespace Microsoft.CodeAnalysis.Diagnostics;
///
-/// Provides C# and VB analyzers a convenient access to common editorconfig options with fallback to IDE default values.
+/// Provides C# and VB analyzers a convenient access to common editorconfig options.
///
-internal readonly struct AnalyzerOptionsProvider(IOptionsReader options, string language, IdeAnalyzerOptions fallbackOptions)
+internal readonly struct AnalyzerOptionsProvider(IOptionsReader options, string language)
{
- ///
- /// Document editorconfig options.
- ///
- private readonly IOptionsReader _options = options;
-
- ///
- /// Fallback options - the default options in Code Style layer.
- ///
- private readonly IdeAnalyzerOptions _fallbackOptions = fallbackOptions;
-
- private readonly string _language = language;
-
- public AnalyzerOptionsProvider(IOptionsReader options, string language, AnalyzerOptions fallbackOptions)
- : this(options, language, fallbackOptions.GetIdeOptions())
- {
- }
-
// SimplifierOptions
- public CodeStyleOption2 QualifyFieldAccess => GetOption(CodeStyleOptions2.QualifyFieldAccess, FallbackSimplifierOptions.QualifyFieldAccess);
- public CodeStyleOption2 QualifyPropertyAccess => GetOption(CodeStyleOptions2.QualifyPropertyAccess, FallbackSimplifierOptions.QualifyPropertyAccess);
- public CodeStyleOption2 QualifyMethodAccess => GetOption(CodeStyleOptions2.QualifyMethodAccess, FallbackSimplifierOptions.QualifyMethodAccess);
- public CodeStyleOption2 QualifyEventAccess => GetOption(CodeStyleOptions2.QualifyEventAccess, FallbackSimplifierOptions.QualifyEventAccess);
- public CodeStyleOption2 PreferPredefinedTypeKeywordInMemberAccess => GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, FallbackSimplifierOptions.PreferPredefinedTypeKeywordInMemberAccess);
- public CodeStyleOption2 PreferPredefinedTypeKeywordInDeclaration => GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, FallbackSimplifierOptions.PreferPredefinedTypeKeywordInDeclaration);
+ public CodeStyleOption2 QualifyFieldAccess => GetOption(CodeStyleOptions2.QualifyFieldAccess);
+ public CodeStyleOption2 QualifyPropertyAccess => GetOption(CodeStyleOptions2.QualifyPropertyAccess);
+ public CodeStyleOption2 QualifyMethodAccess => GetOption(CodeStyleOptions2.QualifyMethodAccess);
+ public CodeStyleOption2 QualifyEventAccess => GetOption(CodeStyleOptions2.QualifyEventAccess);
+ public CodeStyleOption2 PreferPredefinedTypeKeywordInMemberAccess => GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess);
+ public CodeStyleOption2 PreferPredefinedTypeKeywordInDeclaration => GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration);
public SimplifierOptions GetSimplifierOptions(ISimplification simplification)
- => simplification.GetSimplifierOptions(_options);
+ => simplification.GetSimplifierOptions(options);
// SyntaxFormattingOptions
public SyntaxFormattingOptions GetSyntaxFormattingOptions(ISyntaxFormatting formatting)
- => formatting.GetFormattingOptions(_options, _fallbackOptions.CleanupOptions?.FormattingOptions);
+ => formatting.GetFormattingOptions(options);
// CodeGenerationOptions
- public NamingStylePreferences NamingPreferences => GetOption(NamingStyleOptions.NamingPreferences, _fallbackOptions.GenerationOptions?.NamingStyle ?? NamingStylePreferences.Default);
+ public NamingStylePreferences NamingPreferences => GetOption(NamingStyleOptions.NamingPreferences);
// CodeStyleOptions
- public CodeStyleOption2 PreferObjectInitializer => GetOption(CodeStyleOptions2.PreferObjectInitializer, FallbackCodeStyleOptions.PreferObjectInitializer);
- public CodeStyleOption2 PreferCollectionExpression => GetOption(CodeStyleOptions2.PreferCollectionExpression, FallbackCodeStyleOptions.PreferCollectionExpression);
- public CodeStyleOption2 PreferCollectionInitializer => GetOption(CodeStyleOptions2.PreferCollectionInitializer, FallbackCodeStyleOptions.PreferCollectionInitializer);
- public CodeStyleOption2 PreferSimplifiedBooleanExpressions => GetOption(CodeStyleOptions2.PreferSimplifiedBooleanExpressions, FallbackCodeStyleOptions.PreferSimplifiedBooleanExpressions);
- public OperatorPlacementWhenWrappingPreference OperatorPlacementWhenWrapping => GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping, FallbackCodeStyleOptions.OperatorPlacementWhenWrapping);
- public CodeStyleOption2 PreferCoalesceExpression => GetOption(CodeStyleOptions2.PreferCoalesceExpression, FallbackCodeStyleOptions.PreferCoalesceExpression);
- public CodeStyleOption2 PreferNullPropagation => GetOption(CodeStyleOptions2.PreferNullPropagation, FallbackCodeStyleOptions.PreferNullPropagation);
- public CodeStyleOption2 PreferExplicitTupleNames => GetOption(CodeStyleOptions2.PreferExplicitTupleNames, FallbackCodeStyleOptions.PreferExplicitTupleNames);
- public CodeStyleOption2 PreferAutoProperties => GetOption(CodeStyleOptions2.PreferAutoProperties, FallbackCodeStyleOptions.PreferAutoProperties);
- public CodeStyleOption2 PreferInferredTupleNames => GetOption(CodeStyleOptions2.PreferInferredTupleNames, FallbackCodeStyleOptions.PreferInferredTupleNames);
- public CodeStyleOption2 PreferInferredAnonymousTypeMemberNames => GetOption(CodeStyleOptions2.PreferInferredAnonymousTypeMemberNames, FallbackCodeStyleOptions.PreferInferredAnonymousTypeMemberNames);
- public CodeStyleOption2 PreferIsNullCheckOverReferenceEqualityMethod => GetOption(CodeStyleOptions2.PreferIsNullCheckOverReferenceEqualityMethod, FallbackCodeStyleOptions.PreferIsNullCheckOverReferenceEqualityMethod);
- public CodeStyleOption2 PreferConditionalExpressionOverAssignment => GetOption(CodeStyleOptions2.PreferConditionalExpressionOverAssignment, FallbackCodeStyleOptions.PreferConditionalExpressionOverAssignment);
- public CodeStyleOption2 PreferConditionalExpressionOverReturn => GetOption(CodeStyleOptions2.PreferConditionalExpressionOverReturn, FallbackCodeStyleOptions.PreferConditionalExpressionOverReturn);
- public CodeStyleOption2 PreferCompoundAssignment => GetOption(CodeStyleOptions2.PreferCompoundAssignment, FallbackCodeStyleOptions.PreferCompoundAssignment);
- public CodeStyleOption2 PreferSimplifiedInterpolation => GetOption(CodeStyleOptions2.PreferSimplifiedInterpolation, FallbackCodeStyleOptions.PreferSimplifiedInterpolation);
+ public CodeStyleOption2 PreferObjectInitializer => GetOption(CodeStyleOptions2.PreferObjectInitializer);
+ public CodeStyleOption2 PreferCollectionExpression => GetOption(CodeStyleOptions2.PreferCollectionExpression);
+ public CodeStyleOption2 PreferCollectionInitializer => GetOption(CodeStyleOptions2.PreferCollectionInitializer);
+ public CodeStyleOption2 PreferSimplifiedBooleanExpressions => GetOption(CodeStyleOptions2.PreferSimplifiedBooleanExpressions);
+ public OperatorPlacementWhenWrappingPreference OperatorPlacementWhenWrapping => GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping);
+ public CodeStyleOption2 PreferCoalesceExpression => GetOption(CodeStyleOptions2.PreferCoalesceExpression);
+ public CodeStyleOption2 PreferNullPropagation => GetOption(CodeStyleOptions2.PreferNullPropagation);
+ public CodeStyleOption2 PreferExplicitTupleNames => GetOption(CodeStyleOptions2.PreferExplicitTupleNames);
+ public CodeStyleOption2 PreferAutoProperties => GetOption(CodeStyleOptions2.PreferAutoProperties);
+ public CodeStyleOption2 PreferInferredTupleNames => GetOption(CodeStyleOptions2.PreferInferredTupleNames);
+ public CodeStyleOption2 PreferInferredAnonymousTypeMemberNames => GetOption(CodeStyleOptions2.PreferInferredAnonymousTypeMemberNames);
+ public CodeStyleOption2 PreferIsNullCheckOverReferenceEqualityMethod => GetOption(CodeStyleOptions2.PreferIsNullCheckOverReferenceEqualityMethod);
+ public CodeStyleOption2 PreferConditionalExpressionOverAssignment => GetOption(CodeStyleOptions2.PreferConditionalExpressionOverAssignment);
+ public CodeStyleOption2 PreferConditionalExpressionOverReturn => GetOption(CodeStyleOptions2.PreferConditionalExpressionOverReturn);
+ public CodeStyleOption2 PreferCompoundAssignment => GetOption(CodeStyleOptions2.PreferCompoundAssignment);
+ public CodeStyleOption2 PreferSimplifiedInterpolation => GetOption(CodeStyleOptions2.PreferSimplifiedInterpolation);
public CodeStyleOption2 PreferSystemHashCode => GetOption(CodeStyleOptions2.PreferSystemHashCode);
- public CodeStyleOption2 UnusedParameters => GetOption(CodeStyleOptions2.UnusedParameters, FallbackCodeStyleOptions.UnusedParameters);
- public CodeStyleOption2 RequireAccessibilityModifiers => GetOption(CodeStyleOptions2.AccessibilityModifiersRequired, FallbackCodeStyleOptions.AccessibilityModifiersRequired);
- public CodeStyleOption2 PreferReadonly => GetOption(CodeStyleOptions2.PreferReadonly, FallbackCodeStyleOptions.PreferReadonly);
- public CodeStyleOption2 ArithmeticBinaryParentheses => GetOption(CodeStyleOptions2.ArithmeticBinaryParentheses, FallbackCodeStyleOptions.ArithmeticBinaryParentheses);
- public CodeStyleOption2 OtherBinaryParentheses => GetOption(CodeStyleOptions2.OtherBinaryParentheses, FallbackCodeStyleOptions.OtherBinaryParentheses);
- public CodeStyleOption2 RelationalBinaryParentheses => GetOption(CodeStyleOptions2.RelationalBinaryParentheses, FallbackCodeStyleOptions.RelationalBinaryParentheses);
- public CodeStyleOption2 OtherParentheses => GetOption(CodeStyleOptions2.OtherParentheses, FallbackCodeStyleOptions.OtherParentheses);
- public CodeStyleOption2 ForEachExplicitCastInSource => GetOption(CodeStyleOptions2.ForEachExplicitCastInSource, FallbackCodeStyleOptions.ForEachExplicitCastInSource);
- public CodeStyleOption2 PreferNamespaceAndFolderMatchStructure => GetOption(CodeStyleOptions2.PreferNamespaceAndFolderMatchStructure, FallbackCodeStyleOptions.PreferNamespaceAndFolderMatchStructure);
- public CodeStyleOption2 AllowMultipleBlankLines => GetOption(CodeStyleOptions2.AllowMultipleBlankLines, FallbackCodeStyleOptions.AllowMultipleBlankLines);
- public CodeStyleOption2 AllowStatementImmediatelyAfterBlock => GetOption(CodeStyleOptions2.AllowStatementImmediatelyAfterBlock, FallbackCodeStyleOptions.AllowStatementImmediatelyAfterBlock);
- public string RemoveUnnecessarySuppressionExclusions => GetOption(CodeStyleOptions2.RemoveUnnecessarySuppressionExclusions, FallbackCodeStyleOptions.RemoveUnnecessarySuppressionExclusions);
-
- public string FileHeaderTemplate => GetOption(CodeStyleOptions2.FileHeaderTemplate, defaultValue: string.Empty); // no fallback IDE option
-
- private TValue GetOption(Option2 option, TValue defaultValue)
- => _options.GetOption(option, defaultValue);
+ public CodeStyleOption2 UnusedParameters => GetOption(CodeStyleOptions2.UnusedParameters);
+ public CodeStyleOption2 RequireAccessibilityModifiers => GetOption(CodeStyleOptions2.AccessibilityModifiersRequired);
+ public CodeStyleOption2 PreferReadonly => GetOption(CodeStyleOptions2.PreferReadonly);
+ public CodeStyleOption2 ArithmeticBinaryParentheses => GetOption(CodeStyleOptions2.ArithmeticBinaryParentheses);
+ public CodeStyleOption2 OtherBinaryParentheses => GetOption(CodeStyleOptions2.OtherBinaryParentheses);
+ public CodeStyleOption2 RelationalBinaryParentheses => GetOption(CodeStyleOptions2.RelationalBinaryParentheses);
+ public CodeStyleOption2 OtherParentheses => GetOption(CodeStyleOptions2.OtherParentheses);
+ public CodeStyleOption2 ForEachExplicitCastInSource => GetOption(CodeStyleOptions2.ForEachExplicitCastInSource);
+ public CodeStyleOption2 PreferNamespaceAndFolderMatchStructure => GetOption(CodeStyleOptions2.PreferNamespaceAndFolderMatchStructure);
+ public CodeStyleOption2 AllowMultipleBlankLines => GetOption(CodeStyleOptions2.AllowMultipleBlankLines);
+ public CodeStyleOption2 AllowStatementImmediatelyAfterBlock => GetOption(CodeStyleOptions2.AllowStatementImmediatelyAfterBlock);
+ public string RemoveUnnecessarySuppressionExclusions => GetOption(CodeStyleOptions2.RemoveUnnecessarySuppressionExclusions);
+
+ public string FileHeaderTemplate => GetOption(CodeStyleOptions2.FileHeaderTemplate);
public TValue GetOption(PerLanguageOption2 option)
- => _options.GetOption(option, _language);
+ => options.GetOption(option, language);
- private TValue GetOption(PerLanguageOption2 option, TValue defaultValue)
- => _options.GetOption(option, _language, defaultValue);
-
- private IdeCodeStyleOptions FallbackCodeStyleOptions
- => _fallbackOptions.CodeStyleOptions ?? IdeCodeStyleOptions.CommonDefaults;
-
- private SimplifierOptions FallbackSimplifierOptions
- => _fallbackOptions.CleanupOptions?.SimplifierOptions ?? SimplifierOptions.CommonDefaults;
+ private TValue GetOption(Option2 option)
+ => options.GetOption(option);
internal IOptionsReader GetAnalyzerConfigOptions()
- => _options;
-
- internal IdeAnalyzerOptions GetFallbackOptions()
- => _fallbackOptions;
+ => options;
}
internal static partial class AnalyzerOptionsProviders
@@ -126,7 +91,7 @@ public static IdeAnalyzerOptions GetIdeOptions(this AnalyzerOptions options)
#endif
public static AnalyzerOptionsProvider GetAnalyzerOptions(this AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree)
- => new(analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader(), syntaxTree.Options.Language, analyzerOptions);
+ => new(analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader(), syntaxTree.Options.Language);
public static AnalyzerOptionsProvider GetAnalyzerOptions(this SemanticModelAnalysisContext context)
=> GetAnalyzerOptions(context.Options, context.SemanticModel.SyntaxTree);
@@ -148,13 +113,4 @@ public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this SemanticModelAnalysi
public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this SyntaxNodeAnalysisContext context)
=> context.Options.GetIdeOptions();
-
- public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this SyntaxTreeAnalysisContext context)
- => context.Options.GetIdeOptions();
-
- public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this OperationAnalysisContext context)
- => context.Options.GetIdeOptions();
-
- public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this CodeBlockAnalysisContext context)
- => context.Options.GetIdeOptions();
}
diff --git a/src/Analyzers/Core/CodeFixes/AnalyzerOptionsProviders.cs b/src/Analyzers/Core/CodeFixes/AnalyzerOptionsProviders.cs
index c799a31e569e9..e270d3156c84e 100644
--- a/src/Analyzers/Core/CodeFixes/AnalyzerOptionsProviders.cs
+++ b/src/Analyzers/Core/CodeFixes/AnalyzerOptionsProviders.cs
@@ -2,11 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Threading;
using System.Threading.Tasks;
-using System.Collections.Generic;
-using System.Text;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Options;
@@ -20,6 +17,6 @@ public static async ValueTask GetAnalyzerOptionsProvide
var analyzerOptions = document.Project.AnalyzerOptions;
var configOptions = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader();
- return new AnalyzerOptionsProvider(configOptions, document.Project.Language, analyzerOptions);
+ return new AnalyzerOptionsProvider(configOptions, document.Project.Language);
}
}
diff --git a/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb b/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb
index 8e24a0c492cd1..324ccd7641048 100644
--- a/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb
+++ b/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb
@@ -18,83 +18,61 @@ Namespace Microsoft.CodeAnalysis.Diagnostics
'''
Private ReadOnly _options As IOptionsReader
- '''
- ''' Fallback options - the default options in Code Style layer.
- '''
- Private ReadOnly _fallbackOptions As IdeAnalyzerOptions
-
- Public Sub New(options As IOptionsReader, fallbackOptions As IdeAnalyzerOptions)
+ Public Sub New(options As IOptionsReader)
_options = options
- _fallbackOptions = fallbackOptions
- End Sub
-
- Public Sub New(options As IOptionsReader, fallbackOptions As AnalyzerOptions)
- MyClass.New(options, fallbackOptions.GetIdeOptions())
End Sub
Public Function GetSimplifierOptions() As VisualBasicSimplifierOptions
- Return New VisualBasicSimplifierOptions(_options, FallbackSimplifierOptions)
+ Return New VisualBasicSimplifierOptions(_options, fallbackOptions:=Nothing)
End Function
Public ReadOnly Property PreferredModifierOrder As CodeStyleOption2(Of String)
Get
- Return GetOption(VisualBasicCodeStyleOptions.PreferredModifierOrder, FallbackCodeStyleOptions.PreferredModifierOrder)
+ Return GetOption(VisualBasicCodeStyleOptions.PreferredModifierOrder)
End Get
End Property
Public ReadOnly Property PreferIsNotExpression As CodeStyleOption2(Of Boolean)
Get
- Return GetOption(VisualBasicCodeStyleOptions.PreferIsNotExpression, FallbackCodeStyleOptions.PreferIsNotExpression)
+ Return GetOption(VisualBasicCodeStyleOptions.PreferIsNotExpression)
End Get
End Property
Public ReadOnly Property PreferSimplifiedObjectCreation As CodeStyleOption2(Of Boolean)
Get
- Return GetOption(VisualBasicCodeStyleOptions.PreferSimplifiedObjectCreation, FallbackCodeStyleOptions.PreferSimplifiedObjectCreation)
+ Return GetOption(VisualBasicCodeStyleOptions.PreferSimplifiedObjectCreation)
End Get
End Property
Public ReadOnly Property UnusedValueExpressionStatement As CodeStyleOption2(Of UnusedValuePreference)
Get
- Return GetOption(VisualBasicCodeStyleOptions.UnusedValueExpressionStatement, FallbackCodeStyleOptions.UnusedValueExpressionStatement)
+ Return GetOption(VisualBasicCodeStyleOptions.UnusedValueExpressionStatement)
End Get
End Property
Public ReadOnly Property UnusedValueAssignment As CodeStyleOption2(Of UnusedValuePreference)
Get
- Return GetOption(VisualBasicCodeStyleOptions.UnusedValueAssignment, FallbackCodeStyleOptions.UnusedValueAssignment)
+ Return GetOption(VisualBasicCodeStyleOptions.UnusedValueAssignment)
End Get
End Property
- Private Function GetOption(Of TValue)([option] As Option2(Of CodeStyleOption2(Of TValue)), defaultValue As CodeStyleOption2(Of TValue)) As CodeStyleOption2(Of TValue)
- Return _options.GetOption([option], defaultValue)
+ Private Function GetOption(Of TValue)([option] As Option2(Of CodeStyleOption2(Of TValue))) As CodeStyleOption2(Of TValue)
+ Return _options.GetOption([option])
End Function
- Private ReadOnly Property FallbackSimplifierOptions As VisualBasicSimplifierOptions
- Get
- Return If(DirectCast(_fallbackOptions.CleanupOptions?.SimplifierOptions, VisualBasicSimplifierOptions), VisualBasicSimplifierOptions.Default)
- End Get
- End Property
-
- Private ReadOnly Property FallbackCodeStyleOptions As VisualBasicIdeCodeStyleOptions
- Get
- Return If(DirectCast(_fallbackOptions.CodeStyleOptions, VisualBasicIdeCodeStyleOptions), VisualBasicIdeCodeStyleOptions.Default)
- End Get
- End Property
-
Public Shared Narrowing Operator CType(provider As AnalyzerOptionsProvider) As VisualBasicAnalyzerOptionsProvider
- Return New VisualBasicAnalyzerOptionsProvider(provider.GetAnalyzerConfigOptions(), provider.GetFallbackOptions())
+ Return New VisualBasicAnalyzerOptionsProvider(provider.GetAnalyzerConfigOptions())
End Operator
Public Shared Widening Operator CType(provider As VisualBasicAnalyzerOptionsProvider) As AnalyzerOptionsProvider
- Return New AnalyzerOptionsProvider(provider._options, LanguageNames.VisualBasic, provider._fallbackOptions)
+ Return New AnalyzerOptionsProvider(provider._options, LanguageNames.VisualBasic)
End Operator
End Structure
Friend Module VisualBasicAnalyzerOptionsProviders
Public Function GetVisualBasicAnalyzerOptions(options As AnalyzerOptions, syntaxTree As SyntaxTree) As VisualBasicAnalyzerOptionsProvider
- Return New VisualBasicAnalyzerOptionsProvider(options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader(), options)
+ Return New VisualBasicAnalyzerOptionsProvider(options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree).GetOptionsReader())
End Function
diff --git a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.cs b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.cs
index 800a97a466638..01e209bb2bb5b 100644
--- a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.cs
@@ -622,7 +622,10 @@ protected override BoundExpression FramePointer(SyntaxNode syntax, NamedTypeSymb
// However, frame pointer local variables themselves can be "captured". In that case
// the inner frames contain pointers to the enclosing frames. That is, nested
// frame pointers are organized in a linked list.
- return proxyField.Replacement(syntax, frameType => FramePointer(syntax, frameType));
+ return proxyField.Replacement(
+ syntax,
+ static (frameType, arg) => arg.self.FramePointer(arg.syntax, frameType),
+ (syntax, self: this));
}
var localFrame = (LocalSymbol)framePointer;
@@ -777,7 +780,11 @@ private void InitVariableProxy(SyntaxNode syntax, Symbol symbol, LocalSymbol fra
throw ExceptionUtilities.UnexpectedValue(symbol.Kind);
}
- var left = proxy.Replacement(syntax, frameType1 => new BoundLocal(syntax, framePointer, null, framePointer.Type));
+ var left = proxy.Replacement(
+ syntax,
+ static (frameType1, arg) => new BoundLocal(arg.syntax, arg.framePointer, null, arg.framePointer.Type),
+ (syntax, framePointer));
+
var assignToProxy = new BoundAssignmentOperator(syntax, left, value, value.Type);
if (_currentMethod.MethodKind == MethodKind.Constructor &&
symbol == _currentMethod.ThisParameter &&
diff --git a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs
index 49236fa2a3a89..fbc1881b5924f 100644
--- a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs
@@ -369,7 +369,11 @@ private bool TryReplaceWithProxy(Symbol parameterOrLocal, SyntaxNode syntax, [No
{
if (proxies.TryGetValue(parameterOrLocal, out CapturedSymbolReplacement? proxy))
{
- replacement = proxy.Replacement(syntax, frameType => FramePointer(syntax, frameType));
+ replacement = proxy.Replacement(
+ syntax,
+ static (frameType, arg) => arg.self.FramePointer(arg.syntax, frameType),
+ (syntax, self: this));
+
return true;
}
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs
index 08ddeca6b61a9..a78955a399c9c 100644
--- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs
@@ -23,7 +23,7 @@ public CapturedSymbolReplacement(bool isReusable)
/// Rewrite the replacement expression for the hoisted local so all synthesized field are accessed as members
/// of the appropriate frame.
///
- public abstract BoundExpression Replacement(SyntaxNode node, Func makeFrame);
+ public abstract BoundExpression Replacement(SyntaxNode node, Func makeFrame, TArg arg);
}
internal sealed class CapturedToFrameSymbolReplacement : CapturedSymbolReplacement
@@ -36,9 +36,9 @@ public CapturedToFrameSymbolReplacement(LambdaCapturedVariable hoistedField, boo
this.HoistedField = hoistedField;
}
- public override BoundExpression Replacement(SyntaxNode node, Func makeFrame)
+ public override BoundExpression Replacement(SyntaxNode node, Func makeFrame, TArg arg)
{
- var frame = makeFrame(this.HoistedField.ContainingType);
+ var frame = makeFrame(this.HoistedField.ContainingType, arg);
var field = this.HoistedField.AsMember((NamedTypeSymbol)frame.Type);
return new BoundFieldAccess(node, frame, field, constantValueOpt: null);
}
@@ -54,9 +54,9 @@ public CapturedToStateMachineFieldReplacement(StateMachineFieldSymbol hoistedFie
this.HoistedField = hoistedField;
}
- public override BoundExpression Replacement(SyntaxNode node, Func makeFrame)
+ public override BoundExpression Replacement(SyntaxNode node, Func makeFrame, TArg arg)
{
- var frame = makeFrame(this.HoistedField.ContainingType);
+ var frame = makeFrame(this.HoistedField.ContainingType, arg);
var field = this.HoistedField.AsMember((NamedTypeSymbol)frame.Type);
return new BoundFieldAccess(node, frame, field, constantValueOpt: null);
}
@@ -74,7 +74,7 @@ public CapturedToExpressionSymbolReplacement(BoundExpression replacement, Immuta
this.HoistedFields = hoistedFields;
}
- public override BoundExpression Replacement(SyntaxNode node, Func makeFrame)
+ public override BoundExpression Replacement(SyntaxNode node, Func makeFrame, TArg arg)
{
// By returning the same replacement each time, it is possible we
// are constructing a DAG instead of a tree for the translation.
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
index 25bb0a30587e4..673a6c968cb4c 100644
--- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
@@ -140,7 +140,7 @@ public MethodToStateMachineRewriter(
proxies.TryGetValue(thisParameter, out thisProxy) &&
F.Compilation.Options.OptimizationLevel == OptimizationLevel.Release)
{
- BoundExpression thisProxyReplacement = thisProxy.Replacement(F.Syntax, frameType => F.This());
+ BoundExpression thisProxyReplacement = thisProxy.Replacement(F.Syntax, static (frameType, F) => F.This(), F);
Debug.Assert(thisProxyReplacement.Type is not null);
this.cachedThis = F.SynthesizedLocal(thisProxyReplacement.Type, syntax: F.Syntax, kind: SynthesizedLocalKind.FrameCache);
}
@@ -925,7 +925,7 @@ protected BoundStatement CacheThisIfNeeded()
if ((object)this.cachedThis != null)
{
CapturedSymbolReplacement proxy = proxies[this.OriginalMethod.ThisParameter];
- var fetchThis = proxy.Replacement(F.Syntax, frameType => F.This());
+ var fetchThis = proxy.Replacement(F.Syntax, static (frameType, F) => F.This(), F);
return F.Assignment(F.Local(this.cachedThis), fetchThis);
}
@@ -961,7 +961,7 @@ public sealed override BoundNode VisitThisReference(BoundThisReference node)
else
{
Debug.Assert(proxy != null);
- return proxy.Replacement(F.Syntax, frameType => F.This());
+ return proxy.Replacement(F.Syntax, static (frameType, F) => F.This(), F);
}
}
@@ -977,7 +977,7 @@ public override BoundNode VisitBaseReference(BoundBaseReference node)
CapturedSymbolReplacement proxy = proxies[this.OriginalMethod.ThisParameter];
Debug.Assert(proxy != null);
- return proxy.Replacement(F.Syntax, frameType => F.This());
+ return proxy.Replacement(F.Syntax, static (frameType, F) => F.This(), F);
}
#endregion
diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs
index ef2ad4236dbb8..4720e12ee1dfb 100644
--- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs
@@ -311,7 +311,12 @@ protected BoundStatement GenerateParameterStorage(LocalSymbol stateMachineVariab
CapturedSymbolReplacement proxy;
if (proxies.TryGetValue(method.ThisParameter, out proxy))
{
- bodyBuilder.Add(F.Assignment(proxy.Replacement(F.Syntax, frameType1 => F.Local(stateMachineVariable)), F.This()));
+ var leftExpression = proxy.Replacement(
+ F.Syntax,
+ static (frameType1, arg) => arg.F.Local(arg.stateMachineVariable),
+ (F, stateMachineVariable));
+
+ bodyBuilder.Add(F.Assignment(leftExpression, F.This()));
}
}
@@ -320,8 +325,12 @@ protected BoundStatement GenerateParameterStorage(LocalSymbol stateMachineVariab
CapturedSymbolReplacement proxy;
if (proxies.TryGetValue(parameter, out proxy))
{
- bodyBuilder.Add(F.Assignment(proxy.Replacement(F.Syntax, frameType1 => F.Local(stateMachineVariable)),
- F.Parameter(parameter)));
+ var leftExpression = proxy.Replacement(
+ F.Syntax,
+ static (frameType1, arg) => arg.F.Local(arg.stateMachineVariable),
+ (F, stateMachineVariable));
+
+ bodyBuilder.Add(F.Assignment(leftExpression, F.Parameter(parameter)));
}
}
@@ -456,10 +465,14 @@ protected SynthesizedImplementationMethod GenerateIteratorGetEnumerator(MethodSy
CapturedSymbolReplacement proxy;
if (copyDest.TryGetValue(method.ThisParameter, out proxy))
{
- bodyBuilder.Add(
- F.Assignment(
- proxy.Replacement(F.Syntax, stateMachineType => F.Local(resultVariable)),
- copySrc[method.ThisParameter].Replacement(F.Syntax, stateMachineType => F.This())));
+ var leftExpression = proxy.Replacement(
+ F.Syntax,
+ static (stateMachineType, arg) => arg.F.Local(arg.resultVariable),
+ (F, resultVariable));
+
+ var rightExpression = copySrc[method.ThisParameter].Replacement(F.Syntax, static (stateMachineType, F) => F.This(), F);
+
+ bodyBuilder.Add(F.Assignment(leftExpression, rightExpression));
}
}
@@ -471,9 +484,13 @@ protected SynthesizedImplementationMethod GenerateIteratorGetEnumerator(MethodSy
if (copyDest.TryGetValue(parameter, out proxy))
{
// result.parameter
- BoundExpression resultParameter = proxy.Replacement(F.Syntax, stateMachineType => F.Local(resultVariable));
+ BoundExpression resultParameter = proxy.Replacement(
+ F.Syntax,
+ static (stateMachineType, arg) => arg.F.Local(arg.resultVariable),
+ (F, resultVariable));
+
// this.parameterProxy
- BoundExpression parameterProxy = copySrc[parameter].Replacement(F.Syntax, stateMachineType => F.This());
+ BoundExpression parameterProxy = copySrc[parameter].Replacement(F.Syntax, static (stateMachineType, F) => F.This(), F);
BoundStatement copy = InitializeParameterField(getEnumeratorMethod, parameter, resultParameter, parameterProxy);
bodyBuilder.Add(copy);
diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
index 31c2e242c1c8e..887dfabee8fb7 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
@@ -7223,18 +7223,79 @@ bool canFollowNullableType()
case ParseTypeMode.AfterIs:
case ParseTypeMode.DefinitePattern:
case ParseTypeMode.AsExpression:
- // These contexts might be a type that is at the end of an expression. In these contexts we only
- // permit the nullable qualifier if it is followed by a token that could not start an
- // expression, because for backward compatibility we want to consider a `?` token as part of the
- // `?:` operator if possible.
+ // We are currently after `?` token after a nullable type pattern and need to decide how to
+ // parse what we see next. In the case of an identifier (e.g. `x ? a` there are two ways we can
+ // see things
//
- // Similarly, if we have `T?[]` we do want to treat that as an array of nullables (following
- // existing parsing), not a conditional that returns a list.
+ // 1. As a start of conditional expression, e.g. `var a = obj is string ? a : b`
+ // 2. As a designation of a nullable-typed pattern, e.g. `if (obj is string? str)`
+ //
+ // Since nullable types (no matter reference or value types) are not valid in patterns by
+ // default we are biased towards the first option and consider case 2 only for error recovery
+ // purposes (if we parse here as nullable type pattern an error will be reported during
+ // binding). This condition checks for simple cases, where we better use option 2 and parse a
+ // nullable-typed pattern
+ if (IsTrueIdentifier(this.CurrentToken))
+ {
+ // In a non-async method, `await` is a simple identifier. However, if we see `x ? await`
+ // it's almost certainly the start of an `await expression` in a conditional expression
+ // (e.g. `x is Y ? await ...`), not a nullable type pattern (since users would not use
+ // 'await' as the name of a variable). So just treat this as a conditional expression.
+ // Similarly, `async` can start a simple lambda in a conditional expression
+ // (e.g. `x is Y ? async a => ...`). The correct behavior is to treat `async` as a keyword
+ if (this.CurrentToken.ContextualKind is SyntaxKind.AsyncKeyword or SyntaxKind.AwaitKeyword)
+ return false;
+
+ var nextTokenKind = PeekToken(1).Kind;
+
+ // These token either 100% end a pattern or start a new one:
+
+ // A literal token starts a new pattern. Can occur in list pattern with missing separation
+ // `,`. For example, in `x is [int[]? arr 5]` we'd prefer to parse this as a missing `,`
+ // after `arr`
+ if (SyntaxFacts.IsLiteral(nextTokenKind))
+ return true;
+
+ // A predefined type is basically the same case: `x is [string[]? slice char ch]`. We'd
+ // prefer to parse this as a missing `,` after `slice`.
+ if (SyntaxFacts.IsPredefinedType(nextTokenKind))
+ return true;
+
+ // `)`, `]` and `}` obviously end a pattern. For example:
+ // `if (x is int? i)`, `indexable[x is string? s]`, `x is { Prop: Type? typeVar }`
+ if (nextTokenKind is SyntaxKind.CloseParenToken or SyntaxKind.CloseBracketToken or SyntaxKind.CloseBraceToken)
+ return true;
+
+ // `{` starts a new pattern. For example: `x is A? { ...`. Note, that `[` and `(` are not
+ // in the list because they can start an invocation/indexer
+ if (nextTokenKind == SyntaxKind.OpenBraceToken)
+ return true;
+
+ // `,` ends a pattern in list/property pattern. For example `x is { Prop1: Type1? type, Prop2: Type2 }` or
+ // `x is [Type1? type, ...]`
+ if (nextTokenKind == SyntaxKind.CommaToken)
+ return true;
+
+ // `;` ends a pattern if it finishes an expression statement: var y = x is bool? b;
+ if (nextTokenKind == SyntaxKind.SemicolonToken)
+ return true;
+
+ // EndOfFileToken is obviously the end of parsing. We are better parsing a pattern rather
+ // than an unfinished conditional expression
+ if (nextTokenKind == SyntaxKind.EndOfFileToken)
+ return true;
+
+ return false;
+ }
+
+ // If nothing from above worked permit the nullable qualifier if it is followed by a token that
+ // could not start an expression. If we have `T?[]` we do want to treat that as an array of
+ // nullables (following existing parsing), not a conditional that returns a list.
return !CanStartExpression() || this.CurrentToken.Kind is SyntaxKind.OpenBracketToken;
case ParseTypeMode.NewExpression:
- // A nullable qualifier is permitted as part of the type in a `new` expression.
- // e.g. `new int?()` is allowed. It creates a null value of type `Nullable`.
- // Similarly `new int? {}` is allowed.
+ // A nullable qualifier is permitted as part of the type in a `new` expression. e.g. `new
+ // int?()` is allowed. It creates a null value of type `Nullable`. Similarly `new int? {}`
+ // is allowed.
return
this.CurrentToken.Kind is SyntaxKind.OpenParenToken or // ctor parameters
SyntaxKind.OpenBracketToken or // array type
diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
index e9b3e9a56cb83..ad961242a9386 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
@@ -50,21 +50,21 @@ when ConvertExpressionToType(expr, out var leftType):
};
}
- private PatternSyntax ParsePattern(Precedence precedence, bool afterIs = false, bool whenIsKeyword = false)
+ private PatternSyntax ParsePattern(Precedence precedence, bool afterIs = false, bool inSwitchArmPattern = false)
{
- return ParseDisjunctivePattern(precedence, afterIs, whenIsKeyword);
+ return ParseDisjunctivePattern(precedence, afterIs, inSwitchArmPattern);
}
- private PatternSyntax ParseDisjunctivePattern(Precedence precedence, bool afterIs, bool whenIsKeyword)
+ private PatternSyntax ParseDisjunctivePattern(Precedence precedence, bool afterIs, bool inSwitchArmPattern)
{
- PatternSyntax result = ParseConjunctivePattern(precedence, afterIs, whenIsKeyword);
+ PatternSyntax result = ParseConjunctivePattern(precedence, afterIs, inSwitchArmPattern);
while (this.CurrentToken.ContextualKind == SyntaxKind.OrKeyword)
{
result = _syntaxFactory.BinaryPattern(
SyntaxKind.OrPattern,
result,
ConvertToKeyword(this.EatToken()),
- ParseConjunctivePattern(precedence, afterIs, whenIsKeyword));
+ ParseConjunctivePattern(precedence, afterIs, inSwitchArmPattern));
}
return result;
@@ -101,16 +101,16 @@ private bool LooksLikeTypeOfPattern()
return false;
}
- private PatternSyntax ParseConjunctivePattern(Precedence precedence, bool afterIs, bool whenIsKeyword)
+ private PatternSyntax ParseConjunctivePattern(Precedence precedence, bool afterIs, bool inSwitchArmPattern)
{
- PatternSyntax result = ParseNegatedPattern(precedence, afterIs, whenIsKeyword);
+ PatternSyntax result = ParseNegatedPattern(precedence, afterIs, inSwitchArmPattern);
while (this.CurrentToken.ContextualKind == SyntaxKind.AndKeyword)
{
result = _syntaxFactory.BinaryPattern(
SyntaxKind.AndPattern,
result,
ConvertToKeyword(this.EatToken()),
- ParseNegatedPattern(precedence, afterIs, whenIsKeyword));
+ ParseNegatedPattern(precedence, afterIs, inSwitchArmPattern));
}
return result;
@@ -155,21 +155,21 @@ private bool ScanDesignation(bool permitTuple)
}
}
- private PatternSyntax ParseNegatedPattern(Precedence precedence, bool afterIs, bool whenIsKeyword)
+ private PatternSyntax ParseNegatedPattern(Precedence precedence, bool afterIs, bool inSwitchArmPattern)
{
if (this.CurrentToken.ContextualKind == SyntaxKind.NotKeyword)
{
return _syntaxFactory.UnaryPattern(
ConvertToKeyword(this.EatToken()),
- ParseNegatedPattern(precedence, afterIs, whenIsKeyword));
+ ParseNegatedPattern(precedence, afterIs, inSwitchArmPattern));
}
else
{
- return ParsePrimaryPattern(precedence, afterIs, whenIsKeyword);
+ return ParsePrimaryPattern(precedence, afterIs, inSwitchArmPattern);
}
}
- private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, bool whenIsKeyword)
+ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, bool inSwitchArmPattern)
{
// handle common error recovery situations during typing
var tk = this.CurrentToken.Kind;
@@ -192,10 +192,10 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b
switch (CurrentToken.Kind)
{
case SyntaxKind.OpenBracketToken:
- return this.ParseListPattern(whenIsKeyword);
+ return this.ParseListPattern(inSwitchArmPattern);
case SyntaxKind.DotDotToken:
return _syntaxFactory.SlicePattern(EatToken(),
- IsPossibleSubpatternElement() ? ParsePattern(precedence, afterIs: false, whenIsKeyword) : null);
+ IsPossibleSubpatternElement() ? ParsePattern(precedence, afterIs: false, inSwitchArmPattern) : null);
case SyntaxKind.LessThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanToken:
@@ -214,7 +214,8 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b
TypeSyntax? type = null;
if (LooksLikeTypeOfPattern())
{
- type = this.ParseType(afterIs ? ParseTypeMode.AfterIs : ParseTypeMode.DefinitePattern);
+ type = this.ParseType(
+ afterIs ? ParseTypeMode.AfterIs : ParseTypeMode.DefinitePattern);
if (type.IsMissing || !CanTokenFollowTypeInPattern(precedence))
{
// either it is not shaped like a type, or it is a constant expression.
@@ -223,7 +224,7 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b
}
}
- var pattern = ParsePatternContinued(type, precedence, whenIsKeyword);
+ var pattern = ParsePatternContinued(type, precedence, inSwitchArmPattern);
if (pattern != null)
return pattern;
@@ -262,14 +263,14 @@ bool CanTokenFollowTypeInPattern(Precedence precedence)
}
}
- private PatternSyntax? ParsePatternContinued(TypeSyntax? type, Precedence precedence, bool whenIsKeyword)
+ private PatternSyntax? ParsePatternContinued(TypeSyntax? type, Precedence precedence, bool inSwitchArmPattern)
{
if (type?.Kind == SyntaxKind.IdentifierName)
{
var typeIdentifier = (IdentifierNameSyntax)type;
var typeIdentifierToken = typeIdentifier.Identifier;
if (typeIdentifierToken.ContextualKind == SyntaxKind.VarKeyword &&
- (this.CurrentToken.Kind == SyntaxKind.OpenParenToken || this.IsValidPatternDesignation(whenIsKeyword)))
+ (this.CurrentToken.Kind == SyntaxKind.OpenParenToken || this.IsValidPatternDesignation(inSwitchArmPattern)))
{
// we have a "var" pattern; "var" is not permitted to be a stand-in for a type (or a constant) in a pattern.
var varToken = ConvertToKeyword(typeIdentifierToken);
@@ -295,7 +296,7 @@ bool CanTokenFollowTypeInPattern(Precedence precedence)
var closeParenToken = this.EatToken(SyntaxKind.CloseParenToken);
parsePropertyPatternClause(out PropertyPatternClauseSyntax? propertyPatternClause0);
- var designation0 = TryParseSimpleDesignation(whenIsKeyword);
+ var designation0 = TryParseSimpleDesignation(inSwitchArmPattern);
if (type == null &&
propertyPatternClause0 == null &&
@@ -333,12 +334,12 @@ bool CanTokenFollowTypeInPattern(Precedence precedence)
{
return _syntaxFactory.RecursivePattern(
type, positionalPatternClause: null, propertyPatternClause,
- TryParseSimpleDesignation(whenIsKeyword));
+ TryParseSimpleDesignation(inSwitchArmPattern));
}
if (type != null)
{
- var designation = TryParseSimpleDesignation(whenIsKeyword);
+ var designation = TryParseSimpleDesignation(inSwitchArmPattern);
if (designation != null)
return _syntaxFactory.DeclarationPattern(type, designation);
@@ -431,7 +432,7 @@ private CSharpSyntaxNode ParseExpressionOrPatternForSwitchStatement()
{
var savedState = _termState;
_termState |= TerminatorState.IsExpressionOrPatternInCaseLabelOfSwitchStatement;
- var pattern = ParsePattern(Precedence.Conditional, whenIsKeyword: true);
+ var pattern = ParsePattern(Precedence.Conditional, inSwitchArmPattern: true);
_termState = savedState;
return ConvertPatternToExpressionIfPossible(pattern);
}
@@ -589,7 +590,7 @@ SeparatedSyntaxList parseSwitchExpressionArms()
var savedState = _termState;
_termState |= TerminatorState.IsPatternInSwitchExpressionArm;
- var pattern = ParsePattern(Precedence.Coalescing, whenIsKeyword: true);
+ var pattern = ParsePattern(Precedence.Coalescing, inSwitchArmPattern: true);
_termState = savedState;
// We use a precedence that excludes lambdas, assignments, and a conditional which could have a
@@ -628,7 +629,7 @@ SeparatedSyntaxList parseSwitchExpressionArms()
}
}
- private ListPatternSyntax ParseListPattern(bool whenIsKeyword)
+ private ListPatternSyntax ParseListPattern(bool inSwitchArmPattern)
{
var openBracket = this.EatToken(SyntaxKind.OpenBracketToken);
var list = this.ParseCommaSeparatedSyntaxList(
@@ -645,7 +646,7 @@ private ListPatternSyntax ParseListPattern(bool whenIsKeyword)
openBracket,
list,
this.EatToken(SyntaxKind.CloseBracketToken),
- TryParseSimpleDesignation(whenIsKeyword));
+ TryParseSimpleDesignation(inSwitchArmPattern));
}
}
}
diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests.cs
index ac537827d6664..2e6c81c785b24 100644
--- a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests.cs
+++ b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests.cs
@@ -4773,26 +4773,28 @@ public static void Main(object o)
private static object M() => null;
}";
var compilation = CreateCompilation(program).VerifyDiagnostics(
- // (9,32): error CS1525: Invalid expression term 'break'
- // case Color? Color2:
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("break").WithLocation(9, 32),
- // (9,32): error CS1003: Syntax error, ':' expected
- // case Color? Color2:
- Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(9, 32),
// (8,18): error CS0118: 'Color' is a variable but is used like a type
// case Color Color:
Diagnostic(ErrorCode.ERR_BadSKknown, "Color").WithArguments("Color", "variable", "type").WithLocation(8, 18),
// (9,25): error CS0103: The name 'Color2' does not exist in the current context
// case Color? Color2:
- Diagnostic(ErrorCode.ERR_NameNotInContext, "Color2").WithArguments("Color2").WithLocation(9, 25)
- );
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "Color2").WithArguments("Color2").WithLocation(9, 25),
+ // (9,32): error CS1525: Invalid expression term 'break'
+ // case Color? Color2:
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("break").WithLocation(9, 32),
+ // (9,32): error CS1003: Syntax error, ':' expected
+ // case Color? Color2:
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(9, 32));
+
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var colorDecl = GetPatternDeclarations(tree, "Color").ToArray();
var colorRef = GetReferences(tree, "Color").ToArray();
+
Assert.Equal(1, colorDecl.Length);
Assert.Equal(2, colorRef.Length);
+
Assert.Null(model.GetSymbolInfo(colorRef[0]).Symbol);
VerifyModelForDeclarationOrVarSimplePattern(model, colorDecl[0], colorRef[1]);
}
diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests2.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests2.cs
index 8b28cfd8f6468..3cf79e3499614 100644
--- a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests2.cs
+++ b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests2.cs
@@ -4,11 +4,7 @@
#nullable disable
-using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
@@ -2680,7 +2676,7 @@ public void M(string s)
);
}
- [Fact]
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
public void IsNullableReferenceType_01()
{
var source =
@@ -2712,25 +2708,12 @@ public void M5(object o) {
// (10,22): error CS8650: It is not legal to use nullable reference type 'string?' in an is-type expression; use the underlying type 'string' instead.
// var t = o is string?;
Diagnostic(ErrorCode.ERR_IsNullableType, "string?").WithArguments("string").WithLocation(10, 22),
- // (13,30): error CS0103: The name '_' does not exist in the current context
- // var t = o is string? _;
- Diagnostic(ErrorCode.ERR_NameNotInContext, "_").WithArguments("_").WithLocation(13, 30),
- // (13,31): error CS1003: Syntax error, ':' expected
- // var t = o is string? _;
- Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(":").WithLocation(13, 31),
- // (13,31): error CS1525: Invalid expression term ';'
+ // (13,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
// var t = o is string? _;
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(13, 31),
- // (16,22): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'object', with 2 out parameters and a void return type.
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(13, 22),
+ // (16,23): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
// var t = o is (string? _);
- Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(string? _)").WithArguments("object", "2").WithLocation(16, 22),
- // (16,29): error CS1003: Syntax error, ',' expected
- // var t = o is (string? _);
- Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(",").WithLocation(16, 29),
- // (16,31): error CS1003: Syntax error, ',' expected
- // var t = o is (string? _);
- Diagnostic(ErrorCode.ERR_SyntaxError, "_").WithArguments(",").WithLocation(16, 31)
- );
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(16, 23));
}
[Fact]
diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests4.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests4.cs
index 9f8814f4ecf8b..4665233220ada 100644
--- a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests4.cs
+++ b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests4.cs
@@ -3759,11 +3759,11 @@ public class A
static void M(object o, bool c)
{
if (o is A?) { } // error 1 (can't test for is nullable reference type)
- if (o is A? b1) { } // error 2 (missing :)
+ if (o is A? b1) { } // error 2 (can't test for is nullable reference type)
if (o is A? b2 && c) { } // error 3 (missing :)
- if (o is A[]? b5) { } // error 4 (missing :)
+ if (o is A[]? b5) { } // error 4 (can't test for is nullable reference type)
if (o is A[]? b6 && c) { } // error 5 (missing :)
- if (o is A[][]? b7) { } // error 6 (missing :)
+ if (o is A[][]? b7) { } // error 6 (can't test for is nullable reference type)
if (o is A[][]? b8 && c) { } // error 7 (missing :)
if (o is A? && c) { } // error 8 (can't test for is nullable reference type)
_ = o is A[][]?; // error 9 (can't test for is nullable reference type)
@@ -3776,36 +3776,27 @@ static void M(object o, bool c)
// (7,18): error CS8650: It is not legal to use nullable reference type 'A?' in an is-type expression; use the underlying type 'A' instead.
// if (o is A?) { } // error 1 (can't test for is nullable reference type)
Diagnostic(ErrorCode.ERR_IsNullableType, "A?").WithArguments("A").WithLocation(7, 18),
- // (8,23): error CS1003: Syntax error, ':' expected
- // if (o is A? b1) { } // error 2 (missing :)
- Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(8, 23),
- // (8,23): error CS1525: Invalid expression term ')'
- // if (o is A? b1) { } // error 2 (missing :)
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(8, 23),
- // (9,28): error CS1003: Syntax error, ':' expected
+ // 0.cs(8,18): error CS8116: It is not legal to use nullable reference type 'A?' in an is-type expression; use the underlying type 'A' instead.
+ // if (o is A? b1) { } // error 2 (can't test for is nullable reference type)
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "A?").WithArguments("A").WithLocation(8, 18),
+ // 0.cs(9,28): error CS1003: Syntax error, ':' expected
// if (o is A? b2 && c) { } // error 3 (missing :)
Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(9, 28),
// (9,28): error CS1525: Invalid expression term ')'
// if (o is A? b2 && c) { } // error 3 (missing :)
Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(9, 28),
- // (10,25): error CS1003: Syntax error, ':' expected
- // if (o is A[]? b5) { } // error 4 (missing :)
- Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(10, 25),
- // (10,25): error CS1525: Invalid expression term ')'
- // if (o is A[]? b5) { } // error 4 (missing :)
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(10, 25),
+ // (10,18): error CS8116: It is not legal to use nullable reference type 'A[]?' in an is-type expression; use the underlying type 'A[]' instead.
+ // if (o is A[]? b5) { } // error 4 (can't test for is nullable reference type)
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "A[]?").WithArguments("A[]").WithLocation(10, 18),
// (11,30): error CS1003: Syntax error, ':' expected
// if (o is A[]? b6 && c) { } // error 5 (missing :)
Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(11, 30),
// (11,30): error CS1525: Invalid expression term ')'
// if (o is A[]? b6 && c) { } // error 5 (missing :)
Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(11, 30),
- // (12,27): error CS1003: Syntax error, ':' expected
- // if (o is A[][]? b7) { } // error 6 (missing :)
- Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(12, 27),
- // (12,27): error CS1525: Invalid expression term ')'
- // if (o is A[][]? b7) { } // error 6 (missing :)
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(12, 27),
+ // (12,18): error CS8116: It is not legal to use nullable reference type 'A[][]?' in an is-type expression; use the underlying type 'A[][]' instead.
+ // if (o is A[][]? b7) { } // error 6 (can't test for is nullable reference type)
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "A[][]?").WithArguments("A[][]").WithLocation(12, 18),
// (13,32): error CS1003: Syntax error, ':' expected
// if (o is A[][]? b8 && c) { } // error 7 (missing :)
Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(13, 32),
diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests_NullableTypes.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests_NullableTypes.cs
new file mode 100644
index 0000000000000..ecfa3b7758616
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Emit2/Semantics/PatternMatchingTests_NullableTypes.cs
@@ -0,0 +1,675 @@
+// Licensed to the .NET Foundation under one or more 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.Test.Utilities;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests;
+
+public class PatternMatchingTests_NullableTypes : PatternMatchingTestBase
+{
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PatternCombinations()
+ {
+ var source = """
+ #nullable enable
+
+ class C
+ {
+ void M(object obj)
+ {
+ if (obj is int? or string?) { }
+ if (obj is int? i1 or string? s) { }
+ if (obj is int? and { }) { }
+ if (obj is int? i2 and { }) { }
+ if (obj is int? i3 and (1, 2)) { }
+ if (obj is int? i4 and []) { }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (7,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (obj is int? or string?) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(7, 20),
+ // (7,28): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (obj is int? or string?) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(7, 28),
+ // (8,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (obj is int? i1 or string? s) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(8, 20),
+ // (8,25): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (obj is int? i1 or string? s) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i1").WithLocation(8, 25),
+ // (8,31): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (obj is int? i1 or string? s) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(8, 31),
+ // (8,39): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (obj is int? i1 or string? s) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s").WithLocation(8, 39),
+ // (9,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (obj is int? and { }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(9, 20),
+ // (10,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (obj is int? i2 and { }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(10, 20),
+ // (11,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (obj is int? i3 and (1, 2)) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(11, 20),
+ // (11,32): error CS1061: 'int' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
+ // if (obj is int? i3 and (1, 2)) { }
+ Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "(1, 2)").WithArguments("int", "Deconstruct").WithLocation(11, 32),
+ // (11,32): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'int', with 2 out parameters and a void return type.
+ // if (obj is int? i3 and (1, 2)) { }
+ Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(1, 2)").WithArguments("int", "2").WithLocation(11, 32),
+ // (12,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (obj is int? i4 and []) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(12, 20),
+ // (12,32): error CS8985: List patterns may not be used for a value of type 'int'. No suitable 'Length' or 'Count' property was found.
+ // if (obj is int? i4 and []) { }
+ Diagnostic(ErrorCode.ERR_ListPatternRequiresLength, "[]").WithArguments("int").WithLocation(12, 32),
+ // (12,32): error CS0518: Predefined type 'System.Index' is not defined or imported
+ // if (obj is int? i4 and []) { }
+ Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[]").WithArguments("System.Index").WithLocation(12, 32),
+ // (12,32): error CS0021: Cannot apply indexing with [] to an expression of type 'int'
+ // if (obj is int? i4 and []) { }
+ Diagnostic(ErrorCode.ERR_BadIndexLHS, "[]").WithArguments("int").WithLocation(12, 32));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PatternCombinations_Arrays()
+ {
+ var source = """
+ #nullable enable
+
+ class C
+ {
+ void M(object obj)
+ {
+ if (obj is int[]? or string[]?) { }
+ if (obj is int[]? i1 or string[]? s) { }
+ if (obj is int[]? and { }) { }
+ if (obj is int[]? i2 and { }) { }
+ if (obj is int[]? i3 and (1, 2)) { }
+ if (obj is int[]? i4 and []) { }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (7,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (obj is int[]? or string[]?) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(7, 20),
+ // (7,30): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (obj is int[]? or string[]?) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(7, 30),
+ // (8,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (obj is int[]? i1 or string[]? s) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(8, 20),
+ // (8,27): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (obj is int[]? i1 or string[]? s) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i1").WithLocation(8, 27),
+ // (8,33): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (obj is int[]? i1 or string[]? s) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(8, 33),
+ // (8,43): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (obj is int[]? i1 or string[]? s) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s").WithLocation(8, 43),
+ // (9,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (obj is int[]? and { }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(9, 20),
+ // (10,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (obj is int[]? i2 and { }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(10, 20),
+ // (11,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (obj is int[]? i3 and (1, 2)) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(11, 20),
+ // (11,34): error CS1061: 'int[]' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'int[]' could be found (are you missing a using directive or an assembly reference?)
+ // if (obj is int[]? i3 and (1, 2)) { }
+ Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "(1, 2)").WithArguments("int[]", "Deconstruct").WithLocation(11, 34),
+ // (11,34): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'int[]', with 2 out parameters and a void return type.
+ // if (obj is int[]? i3 and (1, 2)) { }
+ Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(1, 2)").WithArguments("int[]", "2").WithLocation(11, 34),
+ // (12,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (obj is int[]? i4 and []) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(12, 20),
+ // (12,34): error CS0518: Predefined type 'System.Index' is not defined or imported
+ // if (obj is int[]? i4 and []) { }
+ Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[]").WithArguments("System.Index").WithLocation(12, 34));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PatternsInSwitchStatement()
+ {
+ var source = """
+ using System.Threading.Tasks;
+
+ #nullable enable
+
+ class C
+ {
+ void M(object obj)
+ {
+ var x = 0;
+ switch (obj)
+ {
+ case int?:
+ break;
+ case Task?:
+ break;
+ case int? i1:
+ break;
+ case Task? t1:
+ break;
+ case int? when x > 0:
+ break;
+ case Task? when x > 0:
+ break;
+ case int? i2 when x > 0:
+ break;
+ case Task? t2 when x > 0:
+ break;
+ case (int? when) when x > 0:
+ break;
+ case (Task? when) when x > 0:
+ break;
+ }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (12,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // case int?:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(12, 18),
+ // (14,18): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // case Task?:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(14, 18),
+ // (16,21): error CS1003: Syntax error, ':' expected
+ // case int? i1:
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(":").WithLocation(16, 21),
+ // (16,21): error CS1513: } expected
+ // case int? i1:
+ Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(16, 21),
+ // (16,23): warning CS0164: This label has not been referenced
+ // case int? i1:
+ Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i1").WithLocation(16, 23),
+ // (18,18): error CS0119: 'Task' is a type, which is not valid in the given context
+ // case Task? t1:
+ Diagnostic(ErrorCode.ERR_BadSKunknown, "Task").WithArguments("System.Threading.Tasks.Task", "type").WithLocation(18, 18),
+ // (18,24): error CS0103: The name 't1' does not exist in the current context
+ // case Task? t1:
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "t1").WithArguments("t1").WithLocation(18, 24),
+ // (18,27): error CS1525: Invalid expression term 'break'
+ // case Task? t1:
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("break").WithLocation(18, 27),
+ // (18,27): error CS1003: Syntax error, ':' expected
+ // case Task? t1:
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(18, 27),
+ // (20,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // case int? when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(20, 18),
+ // (22,18): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // case Task? when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(22, 18),
+ // (24,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // case int? i2 when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(24, 18),
+ // (26,18): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // case Task? t2 when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(26, 18),
+ // (28,19): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // case (int? when) when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(28, 19),
+ // (30,19): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // case (Task? when) when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(30, 19));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PatternsInSwitchStatement_Arrays()
+ {
+ var source = """
+ using System.Threading.Tasks;
+
+ #nullable enable
+
+ class C
+ {
+ void M(object obj)
+ {
+ var x = 0;
+ switch (obj)
+ {
+ case int[]?:
+ break;
+ case Task[]?:
+ break;
+ case int[]? i1:
+ break;
+ case Task[]? t1:
+ break;
+ case int[]? when x > 0:
+ break;
+ case Task[]? when x > 0:
+ break;
+ case int[]? i2 when x > 0:
+ break;
+ case Task[]? t2 when x > 0:
+ break;
+ case (int[]? when) when x > 0:
+ break;
+ case (Task[]? when) when x > 0:
+ break;
+ }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (12,18): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // case int[]?:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(12, 18),
+ // (14,18): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // case Task[]?:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(14, 18),
+ // (16,23): error CS1003: Syntax error, ':' expected
+ // case int[]? i1:
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(":").WithLocation(16, 23),
+ // (16,23): error CS1513: } expected
+ // case int[]? i1:
+ Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(16, 23),
+ // (16,25): warning CS0164: This label has not been referenced
+ // case int[]? i1:
+ Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i1").WithLocation(16, 25),
+ // (18,24): error CS1003: Syntax error, ':' expected
+ // case Task[]? t1:
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(":").WithLocation(18, 24),
+ // (18,24): error CS1513: } expected
+ // case Task[]? t1:
+ Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(18, 24),
+ // (18,26): warning CS0164: This label has not been referenced
+ // case Task[]? t1:
+ Diagnostic(ErrorCode.WRN_UnreferencedLabel, "t1").WithLocation(18, 26),
+ // (20,18): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // case int[]? when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(20, 18),
+ // (22,18): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // case Task[]? when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(22, 18),
+ // (24,18): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // case int[]? i2 when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(24, 18),
+ // (26,18): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // case Task[]? t2 when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(26, 18),
+ // (28,19): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // case (int[]? when) when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(28, 19),
+ // (30,19): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // case (Task[]? when) when x > 0:
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(30, 19));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PatternsInSwitchExpression()
+ {
+ var source = """
+ using System.Threading.Tasks;
+
+ #nullable enable
+
+ class C
+ {
+ void M(object obj)
+ {
+ var x = 0;
+ _ = obj switch
+ {
+ int? => 1,
+ Task? => 2,
+ int? i1 => 3,
+ Task? t1 => 4,
+ int? when x > 0 => 5,
+ Task? when x > 0 => 6,
+ int? i2 when x > 0 => 7,
+ Task? t2 when x > 0 => 8,
+ (int? when) when x > 0 => 9,
+ (Task? when) when x > 0 => 10
+ };
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (12,13): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // int? => 1,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(12, 13),
+ // (13,13): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // Task? => 2,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(13, 13),
+ // (14,16): error CS1003: Syntax error, '=>' expected
+ // int? i1 => 3,
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(14, 16),
+ // (14,16): error CS1525: Invalid expression term '?'
+ // int? i1 => 3,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(14, 16),
+ // (14,25): error CS1003: Syntax error, ':' expected
+ // int? i1 => 3,
+ Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(14, 25),
+ // (14,25): error CS1525: Invalid expression term ','
+ // int? i1 => 3,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(14, 25),
+ // (15,17): error CS1003: Syntax error, '=>' expected
+ // Task? t1 => 4,
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(15, 17),
+ // (15,17): error CS1525: Invalid expression term '?'
+ // Task? t1 => 4,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(15, 17),
+ // (15,26): error CS1003: Syntax error, ':' expected
+ // Task? t1 => 4,
+ Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(15, 26),
+ // (15,26): error CS1525: Invalid expression term ','
+ // Task? t1 => 4,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(15, 26),
+ // (16,13): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // int? when x > 0 => 5,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(16, 13),
+ // (17,13): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // Task? when x > 0 => 6,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(17, 13),
+ // (18,13): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // int? i2 when x > 0 => 7,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(18, 13),
+ // (19,13): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // Task? t2 when x > 0 => 8,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(19, 13),
+ // (20,14): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // (int? when) when x > 0 => 9,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(20, 14),
+ // (21,14): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
+ // (Task? when) when x > 0 => 10
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(21, 14));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PatternsInSwitchExpression_Arrays()
+ {
+ var source = """
+ using System.Threading.Tasks;
+
+ #nullable enable
+
+ class C
+ {
+ void M(object obj)
+ {
+ var x = 0;
+ _ = obj switch
+ {
+ int[]? => 1,
+ Task[]? => 2,
+ int[]? i1 => 3,
+ Task[]? t1 => 4,
+ int[]? when x > 0 => 5,
+ Task[]? when x > 0 => 6,
+ int[]? i2 when x > 0 => 7,
+ Task[]? t2 when x > 0 => 8,
+ (int[]? when) when x > 0 => 9,
+ (Task[]? when) when x > 0 => 10
+ };
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (12,13): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // int[]? => 1,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(12, 13),
+ // (13,13): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // Task[]? => 2,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(13, 13),
+ // (14,18): error CS1003: Syntax error, '=>' expected
+ // int[]? i1 => 3,
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(14, 18),
+ // (14,18): error CS1525: Invalid expression term '?'
+ // int[]? i1 => 3,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(14, 18),
+ // (14,27): error CS1003: Syntax error, ':' expected
+ // int[]? i1 => 3,
+ Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(14, 27),
+ // (14,27): error CS1525: Invalid expression term ','
+ // int[]? i1 => 3,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(14, 27),
+ // (15,19): error CS1003: Syntax error, '=>' expected
+ // Task[]? t1 => 4,
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(15, 19),
+ // (15,19): error CS1525: Invalid expression term '?'
+ // Task[]? t1 => 4,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(15, 19),
+ // (15,28): error CS1003: Syntax error, ':' expected
+ // Task[]? t1 => 4,
+ Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(15, 28),
+ // (15,28): error CS1525: Invalid expression term ','
+ // Task[]? t1 => 4,
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(15, 28),
+ // (16,13): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // int[]? when x > 0 => 5,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(16, 13),
+ // (17,13): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // Task[]? when x > 0 => 6,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(17, 13),
+ // (18,13): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // int[]? i2 when x > 0 => 7,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(18, 13),
+ // (19,13): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // Task[]? t2 when x > 0 => 8,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(19, 13),
+ // (20,14): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // (int[]? when) when x > 0 => 9,
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(20, 14),
+ // (21,14): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
+ // (Task[]? when) when x > 0 => 10
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(21, 14));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PropertySubpatterns()
+ {
+ var source = """
+ #nullable enable
+
+ class E
+ {
+ public object? Prop { get; set; }
+ public object? Prop2 { get; set; }
+ }
+
+ class C
+ {
+ void M(E e)
+ {
+ if (e is { Prop: int? }) { }
+ if (e is { Prop: int? i1 }) { }
+ if (e is { Prop: int? or string? }) { }
+ if (e is { Prop: int? i2 or string? s1 }) { }
+ if (e is { Prop: int?, Prop2: string? }) { }
+ if (e is { Prop: int? i3, Prop2: string? s2 }) { }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (13,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (e is { Prop: int? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(13, 26),
+ // (14,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (e is { Prop: int? i1 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(14, 26),
+ // (15,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (e is { Prop: int? or string? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(15, 26),
+ // (15,34): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (e is { Prop: int? or string? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(15, 34),
+ // (16,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (e is { Prop: int? i2 or string? s1 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(16, 26),
+ // (16,31): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (e is { Prop: int? i2 or string? s1 }) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i2").WithLocation(16, 31),
+ // (16,37): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (e is { Prop: int? i2 or string? s1 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(16, 37),
+ // (16,45): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (e is { Prop: int? i2 or string? s1 }) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s1").WithLocation(16, 45),
+ // (17,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (e is { Prop: int?, Prop2: string? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(17, 26),
+ // (17,39): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (e is { Prop: int?, Prop2: string? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(17, 39),
+ // (18,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
+ // if (e is { Prop: int? i3, Prop2: string? s2 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(18, 26),
+ // (18,42): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (e is { Prop: int? i3, Prop2: string? s2 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(18, 42));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void PropertySubpatterns_Arrays()
+ {
+ var source = """
+ #nullable enable
+
+ class E
+ {
+ public object? Prop { get; set; }
+ public object? Prop2 { get; set; }
+ }
+
+ class C
+ {
+ void M(E e)
+ {
+ if (e is { Prop: int[]? }) { }
+ if (e is { Prop: int[]? i1 }) { }
+ if (e is { Prop: int[]? or string[]? }) { }
+ if (e is { Prop: int[]? i2 or string[]? s1 }) { }
+ if (e is { Prop: int[]?, Prop2: string[]? }) { }
+ if (e is { Prop: int[]? i3, Prop2: string[]? s2 }) { }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (13,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (e is { Prop: int[]? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(13, 26),
+ // (14,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (e is { Prop: int[]? i1 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(14, 26),
+ // (15,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (e is { Prop: int[]? or string[]? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(15, 26),
+ // (15,36): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (e is { Prop: int[]? or string[]? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(15, 36),
+ // (16,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (e is { Prop: int[]? i2 or string[]? s1 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(16, 26),
+ // (16,33): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (e is { Prop: int[]? i2 or string[]? s1 }) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i2").WithLocation(16, 33),
+ // (16,39): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (e is { Prop: int[]? i2 or string[]? s1 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(16, 39),
+ // (16,49): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
+ // if (e is { Prop: int[]? i2 or string[]? s1 }) { }
+ Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s1").WithLocation(16, 49),
+ // (17,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (e is { Prop: int[]?, Prop2: string[]? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(17, 26),
+ // (17,41): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (e is { Prop: int[]?, Prop2: string[]? }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(17, 41),
+ // (18,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
+ // if (e is { Prop: int[]? i3, Prop2: string[]? s2 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(18, 26),
+ // (18,44): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (e is { Prop: int[]? i3, Prop2: string[]? s2 }) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(18, 44));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ListPatterns()
+ {
+ var source = """
+ #nullable enable
+
+ class C
+ {
+ void M2(string s)
+ {
+ if (s is [.. string?]) { }
+ if (s is [.. string? slice1]) { }
+ if (s is [.. string? slice2, ')']) { }
+ }
+ }
+ """;
+
+ var comp = CreateCompilationWithIndexAndRange(source);
+ comp.VerifyDiagnostics(
+ // (7,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (s is [.. string?]) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(7, 22),
+ // (8,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (s is [.. string? slice1]) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(8, 22),
+ // (9,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
+ // if (s is [.. string? slice2, ')']) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(9, 22));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ListPatterns_Arrays()
+ {
+ var source = """
+ #nullable enable
+
+ class C
+ {
+ void M(string[] s)
+ {
+ if (s is [.. string[]?]) { }
+ if (s is [.. string[]? slice1]) { }
+ if (s is [.. string[]? slice2, ")"]) { }
+ }
+ }
+ """;
+
+ var comp = CreateCompilationWithIndexAndRange([source, TestSources.GetSubArray]);
+ comp.VerifyDiagnostics(
+ // (7,22): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (s is [.. string[]?]) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(7, 22),
+ // (8,22): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (s is [.. string[]? slice1]) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(8, 22),
+ // (9,22): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
+ // if (s is [.. string[]? slice2, ')']) { }
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(9, 22));
+ }
+}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs
index 73ba7b40eccba..602da008a3af4 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableTests.cs
@@ -6,11 +6,7 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
using System.Text;
-using Microsoft.CodeAnalysis.CSharp.Symbols;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
@@ -2133,7 +2129,7 @@ struct S
);
}
- [Fact]
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
public void TestIsNullable1()
{
var source = @"
@@ -2149,15 +2145,9 @@ void M(object o)
";
CreateCompilation(source).VerifyDiagnostics(
- // (6,23): error CS0103: The name 'i' does not exist in the current context
- // if (o is int? i)
- Diagnostic(ErrorCode.ERR_NameNotInContext, "i").WithArguments("i").WithLocation(6, 23),
- // (6,24): error CS1003: Syntax error, ':' expected
- // if (o is int? i)
- Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(6, 24),
- // (6,24): error CS1525: Invalid expression term ')'
+ // (6,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
// if (o is int? i)
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(6, 24));
+ Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(6, 18));
}
[Fact]
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/AsyncParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/AsyncParsingTests.cs
index 91a5bf720bf4b..90944462784b9 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/AsyncParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/AsyncParsingTests.cs
@@ -4,9 +4,9 @@
#nullable disable
+using System;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
-using System;
using Xunit;
using Xunit.Abstractions;
@@ -2658,5 +2658,197 @@ public void AsyncAsType_Property_ExplicitInterface()
}
EOF();
}
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AsyncLambdaInConditionalExpressionAfterPattern1()
+ {
+ UsingExpression("x is A ? async b => 0 : null");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "A");
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.SimpleLambdaExpression);
+ {
+ N(SyntaxKind.AsyncKeyword);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.IdentifierToken, "b");
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.NullLiteralExpression);
+ {
+ N(SyntaxKind.NullKeyword);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AsyncLambdaInConditionalExpressionAfterPattern2()
+ {
+ UsingExpression("x is A a ? async b => 0 : null");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "A");
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "a");
+ }
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.SimpleLambdaExpression);
+ {
+ N(SyntaxKind.AsyncKeyword);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.IdentifierToken, "b");
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.NullLiteralExpression);
+ {
+ N(SyntaxKind.NullKeyword);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AsyncLambdaInConditionalExpressionAfterPattern3()
+ {
+ UsingExpression("x is A ? async (b) => 0 : null");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "A");
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.ParenthesizedLambdaExpression);
+ {
+ N(SyntaxKind.AsyncKeyword);
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.IdentifierToken, "b");
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.NullLiteralExpression);
+ {
+ N(SyntaxKind.NullKeyword);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AsyncLambdaInConditionalExpressionAfterPattern4()
+ {
+ UsingExpression("x is A a ? async (b) => 0 : null");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "A");
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "a");
+ }
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.ParenthesizedLambdaExpression);
+ {
+ N(SyntaxKind.AsyncKeyword);
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.IdentifierToken, "b");
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.NullLiteralExpression);
+ {
+ N(SyntaxKind.NullKeyword);
+ }
+ }
+ EOF();
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs
index 56c40064345ad..3479451b547ab 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs
@@ -4,6 +4,7 @@
#nullable disable
+using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
@@ -1147,6 +1148,364 @@ public void AwaitUsingTest()
}
}
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitInConditionalExpressionAfterPattern1()
+ {
+ UsingExpression("x is int ? await y : z");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.AwaitExpression);
+ {
+ N(SyntaxKind.AwaitKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "y");
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "z");
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitInConditionalExpressionAfterPattern2()
+ {
+ UsingExpression("x is int ? await this.SomeMethodAsync() : z");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.AwaitExpression);
+ {
+ N(SyntaxKind.AwaitKeyword);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.SimpleMemberAccessExpression);
+ {
+ N(SyntaxKind.ThisExpression);
+ {
+ N(SyntaxKind.ThisKeyword);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "SomeMethodAsync");
+ }
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "z");
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitInConditionalExpressionAfterPattern3()
+ {
+ UsingExpression("x is int ? await base.SomeMethodAsync() : z");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.AwaitExpression);
+ {
+ N(SyntaxKind.AwaitKeyword);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.SimpleMemberAccessExpression);
+ {
+ N(SyntaxKind.BaseExpression);
+ {
+ N(SyntaxKind.BaseKeyword);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "SomeMethodAsync");
+ }
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "z");
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitInConditionalExpressionAfterPattern4()
+ {
+ UsingExpression("x is int ? await (myTask) : z");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "myTask");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "z");
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitAsStartOfExpressionInConditional1()
+ {
+ UsingExpression("f(x is int? await)",
+ // (1,18): error CS1003: Syntax error, ':' expected
+ // f(x is int? await)
+ Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(1, 18),
+ // (1,18): error CS1525: Invalid expression term ')'
+ // f(x is int? await)
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(1, 18));
+
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "f");
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ M(SyntaxKind.ColonToken);
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitAsStartOfExpressionInConditional2()
+ {
+ UsingExpression("dict[x is int? await]",
+ // (1,21): error CS1003: Syntax error, ':' expected
+ // dict[x is int? await]
+ Diagnostic(ErrorCode.ERR_SyntaxError, "]").WithArguments(":").WithLocation(1, 21),
+ // (1,21): error CS1525: Invalid expression term ']'
+ // dict[x is int? await]
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "]").WithArguments("]").WithLocation(1, 21));
+
+ N(SyntaxKind.ElementAccessExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "dict");
+ }
+ N(SyntaxKind.BracketedArgumentList);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ M(SyntaxKind.ColonToken);
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void AwaitAsStartOfExpressionInConditional3()
+ {
+ UsingExpression("x is { Prop: int? await }",
+ // (1,17): error CS1003: Syntax error, ',' expected
+ // x is { Prop: int? await }
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(",").WithLocation(1, 17),
+ // (1,19): error CS1003: Syntax error, ',' expected
+ // x is { Prop: int? await }
+ Diagnostic(ErrorCode.ERR_SyntaxError, "await").WithArguments(",").WithLocation(1, 19));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
+
#region AwaitExpressionInSyncContext
[Fact]
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationExpressionTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationExpressionTests.cs
index a8dc74a200040..cce90916c45e4 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationExpressionTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationExpressionTests.cs
@@ -5,6 +5,7 @@
#nullable disable
using Microsoft.CodeAnalysis.Test.Utilities;
+using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
@@ -134,17 +135,53 @@ public void NullableTypeTest_02()
EOF();
}
- [Fact]
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
public void NullableTypeTest_03()
{
- UsingStatement("if (e is int? x) {}",
- // (1,16): error CS1003: Syntax error, ':' expected
- // if (e is int? x) {}
- Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(":").WithLocation(1, 16),
- // (1,16): error CS1525: Invalid expression term ')'
- // if (e is int? x) {}
- Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(1, 16)
- );
+ UsingStatement("if (e is int? x) {}");
+
+ N(SyntaxKind.IfStatement);
+ {
+ N(SyntaxKind.IfKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void NullableTypeTest_03_2()
+ {
+ UsingStatement("if (e is int ? x : y) {}");
+
N(SyntaxKind.IfStatement);
{
N(SyntaxKind.IfKeyword);
@@ -168,10 +205,10 @@ public void NullableTypeTest_03()
{
N(SyntaxKind.IdentifierToken, "x");
}
- M(SyntaxKind.ColonToken);
- M(SyntaxKind.IdentifierName);
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.IdentifierName);
{
- M(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.IdentifierToken, "y");
}
}
N(SyntaxKind.CloseParenToken);
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs
index aaacbfe16dcc9..be7321a78f231 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/NullableParsingTests.cs
@@ -688,6 +688,7 @@ public void DeclarationPattern_NullableType()
// (1,25): error CS1003: Syntax error, ':' expected
// switch (e) { case T? t: break; }
Diagnostic(ErrorCode.ERR_SyntaxError, "break").WithArguments(":").WithLocation(1, 25));
+
N(SyntaxKind.SwitchStatement);
{
N(SyntaxKind.SwitchKeyword);
@@ -836,6 +837,7 @@ public void DeclarationPattern_NullableArray()
// (1,22): error CS1513: } expected
// switch (e) { case T[]? t: break; }
Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(1, 22));
+
N(SyntaxKind.SwitchStatement);
{
N(SyntaxKind.SwitchKeyword);
@@ -1774,5 +1776,585 @@ public void CreateNullableArray_07()
}
EOF();
}
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void IsExpressionOfNullableTypeInStatement()
+ {
+ UsingStatement("_ = x is Type?;");
+
+ N(SyntaxKind.ExpressionStatement);
+ {
+ N(SyntaxKind.SimpleAssignmentExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "_");
+ }
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void DeclarationPatternOfNullableTypeInStatement()
+ {
+ UsingStatement("_ = x is Type? t;");
+
+ N(SyntaxKind.ExpressionStatement);
+ {
+ N(SyntaxKind.SimpleAssignmentExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "_");
+ }
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ }
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void DisjunctivePattern_NullableType1()
+ {
+ UsingExpression("x is int? or string?");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.OrPattern);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.OrKeyword);
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void DisjunctivePattern_NullableType2()
+ {
+ UsingExpression("x is int? i or string? s");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.OrPattern);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "i");
+ }
+ }
+ N(SyntaxKind.OrKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "s");
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_NullableType1()
+ {
+ UsingExpression("x is Type? and { }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.AndPattern);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.AndKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_NullableType2()
+ {
+ UsingExpression("x is Type? t and { }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.AndPattern);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ }
+ N(SyntaxKind.AndKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_ConditionalExpressionInsteadOfNullableType3()
+ {
+ UsingExpression("x is Type? and (1, 2)",
+ // (1,22): error CS1003: Syntax error, ':' expected
+ // x is Type? and (1, 2)
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(1, 22),
+ // (1,22): error CS1733: Expected expression
+ // x is Type? and (1, 2)
+ Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 22));
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "and");
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "2");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ M(SyntaxKind.ColonToken);
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_ConditionalExpressionInsteadOfNullableType3_2()
+ {
+ UsingExpression("x is Type ? f(1, 2) : 0");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "f");
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "2");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_NullableType4()
+ {
+ UsingExpression("x is Type? t and (1, 2)");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.AndPattern);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ }
+ N(SyntaxKind.AndKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PositionalPatternClause);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "2");
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_ConditionalExpressionInsteadOfNullableType5()
+ {
+ UsingExpression("x is Type? and []",
+ // (1,17): error CS0443: Syntax error; value expected
+ // x is Type? and []
+ Diagnostic(ErrorCode.ERR_ValueExpected, "]").WithLocation(1, 17),
+ // (1,18): error CS1003: Syntax error, ':' expected
+ // x is Type? and []
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(1, 18),
+ // (1,18): error CS1733: Expected expression
+ // x is Type? and []
+ Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 18));
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.ElementAccessExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "and");
+ }
+ N(SyntaxKind.BracketedArgumentList);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ M(SyntaxKind.Argument);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ M(SyntaxKind.ColonToken);
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_ConditionalExpressionInsteadOfNullableType5_2()
+ {
+ UsingExpression("x is Type ? dict[key] : default");
+
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.ElementAccessExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "dict");
+ }
+ N(SyntaxKind.BracketedArgumentList);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.Argument);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "key");
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.DefaultLiteralExpression);
+ {
+ N(SyntaxKind.DefaultKeyword);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ConjunctivePattern_NullableType6()
+ {
+ UsingExpression("x is Type? t and []");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.AndPattern);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ }
+ N(SyntaxKind.AndKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ }
+ EOF();
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs
index ddc8174b9dbe3..df04aa31a3fa9 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs
@@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
@@ -1361,5 +1362,388 @@ public void MissingClosingAngleBracket07()
}
#endregion
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ExtendedPropertySubpattern_NullableType1()
+ {
+ UsingExpression("e is { Prop: Type? }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ExtendedPropertySubpattern_NullableType2()
+ {
+ UsingExpression("e is { Prop: Type? propVal }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "propVal");
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ExtendedPropertySubpattern_NullableType3()
+ {
+ UsingExpression("e is { Prop: Type? propVal, Prop2: int? val2 }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "propVal");
+ }
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop2");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "val2");
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ExtendedPropertySubpattern_NullableType4()
+ {
+ UsingExpression("e is { Prop: Type? propVal Prop2: int? val2 }",
+ // (1,28): error CS1003: Syntax error, ',' expected
+ // e is { Prop: Type? propVal Prop2: int? val2 }
+ Diagnostic(ErrorCode.ERR_SyntaxError, "Prop2").WithArguments(",").WithLocation(1, 28));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "propVal");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop2");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "val2");
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ExtendedPropertySubpattern_NullableType5()
+ {
+ UsingExpression("e is { Prop: Type? or AnotherType? }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.OrPattern);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.OrKeyword);
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "AnotherType");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void ExtendedPropertySubpattern_NullableType6()
+ {
+ UsingExpression("e is { Prop: Type? t or AnotherType? a }");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.NameColon);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Prop");
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.OrPattern);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ }
+ N(SyntaxKind.OrKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "AnotherType");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "a");
+ }
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ }
+ EOF();
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs
index 0bcd4870ba5af..422e1f3cb456f 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs
@@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
@@ -767,7 +768,7 @@ public void SlicePattern_11()
{
UsingExpression(@"c is [var x ..]",
// (1,13): error CS1003: Syntax error, ',' expected
- // c is {var x ..}
+ // c is [var x ..]
Diagnostic(ErrorCode.ERR_SyntaxError, "..").WithArguments(",").WithLocation(1, 13));
N(SyntaxKind.IsPatternExpression);
@@ -835,7 +836,7 @@ public void SlicePattern_13()
{
UsingExpression(@"c is [[]..]",
// (1,9): error CS1003: Syntax error, ',' expected
- // c is {{}..}
+ // c is [[]..]
Diagnostic(ErrorCode.ERR_SyntaxError, "..").WithArguments(",").WithLocation(1, 9));
N(SyntaxKind.IsPatternExpression);
@@ -1098,6 +1099,508 @@ public void SlicePattern_19()
}
EOF();
}
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_20()
+ {
+ UsingExpression(@"c is [.. string?]");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_21()
+ {
+ UsingExpression(@"c is [.. string? slice]");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_22()
+ {
+ UsingExpression(@"c is [.. string? slice, ')']");
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.CharacterLiteralExpression);
+ {
+ N(SyntaxKind.CharacterLiteralToken);
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_23()
+ {
+ UsingExpression(@"c is [.. string? slice ')']",
+ // (1,24): error CS1003: Syntax error, ',' expected
+ // c is [.. string? slice ')']
+ Diagnostic(ErrorCode.ERR_SyntaxError, "')'").WithArguments(",").WithLocation(1, 24));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.CharacterLiteralExpression);
+ {
+ N(SyntaxKind.CharacterLiteralToken);
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_24()
+ {
+ UsingExpression(@"c is [.. string[]? slice "")""]",
+ // (1,26): error CS1003: Syntax error, ',' expected
+ // c is [.. string[]? slice ")"]
+ Diagnostic(ErrorCode.ERR_SyntaxError, @""")""").WithArguments(",").WithLocation(1, 26));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.ArrayType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.ArrayRankSpecifier);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.OmittedArraySizeExpression);
+ {
+ N(SyntaxKind.OmittedArraySizeExpressionToken);
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.StringLiteralExpression);
+ {
+ N(SyntaxKind.StringLiteralToken, "\")\"");
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_25()
+ {
+ UsingExpression(@"c is [.. int[]? slice 5]",
+ // (1,23): error CS1003: Syntax error, ',' expected
+ // c is [.. int[]? slice 5]
+ Diagnostic(ErrorCode.ERR_SyntaxError, "5").WithArguments(",").WithLocation(1, 23));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.ArrayType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.ArrayRankSpecifier);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.OmittedArraySizeExpression);
+ {
+ N(SyntaxKind.OmittedArraySizeExpressionToken);
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "5");
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_26()
+ {
+ UsingExpression(@"c is [.. int[]? slice int i]",
+ // (1,23): error CS1003: Syntax error, ',' expected
+ // c is [.. int[]? slice int i]
+ Diagnostic(ErrorCode.ERR_SyntaxError, "int").WithArguments(",").WithLocation(1, 23));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.ArrayType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.ArrayRankSpecifier);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.OmittedArraySizeExpression);
+ {
+ N(SyntaxKind.OmittedArraySizeExpressionToken);
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "i");
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_27()
+ {
+ UsingExpression(@"c is [.. string[]? slice string s]",
+ // (1,26): error CS1003: Syntax error, ',' expected
+ // c is [.. string[]? slice string s]
+ Diagnostic(ErrorCode.ERR_SyntaxError, "string").WithArguments(",").WithLocation(1, 26));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.ArrayType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.ArrayRankSpecifier);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.OmittedArraySizeExpression);
+ {
+ N(SyntaxKind.OmittedArraySizeExpressionToken);
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "s");
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void SlicePattern_28()
+ {
+ UsingExpression(@"c is [.. char[]? slice char ch]",
+ // (1,24): error CS1003: Syntax error, ',' expected
+ // c is [.. char[]? slice char ch]
+ Diagnostic(ErrorCode.ERR_SyntaxError, "char").WithArguments(",").WithLocation(1, 24));
+
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "c");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.ListPattern);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.SlicePattern);
+ {
+ N(SyntaxKind.DotDotToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.ArrayType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.CharKeyword);
+ }
+ N(SyntaxKind.ArrayRankSpecifier);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.OmittedArraySizeExpression);
+ {
+ N(SyntaxKind.OmittedArraySizeExpressionToken);
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "slice");
+ }
+ }
+ }
+ M(SyntaxKind.CommaToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.CharKeyword);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "ch");
+ }
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ EOF();
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
index d94f42dd3cfed..1ca8465151f27 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
@@ -5488,6 +5488,329 @@ public void ParseSwitchStatementWithUnclosedPatternAndArrow()
EOF();
}
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestSwitchStatementWithNullableTypeInPattern1()
+ {
+ UsingStatement("""
+ switch (obj)
+ {
+ case Type?:
+ break;
+ }
+ """);
+
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestSwitchStatementWithNullableTypeInPattern2()
+ {
+ UsingStatement("""
+ switch (obj)
+ {
+ case Type? varName:
+ break;
+ }
+ """,
+ // (3,24): error CS1525: Invalid expression term 'break'
+ // case Type? varName:
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("break").WithLocation(3, 24),
+ // (3,24): error CS1003: Syntax error, ':' expected
+ // case Type? varName:
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(3, 24));
+
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CaseSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "varName");
+ }
+ N(SyntaxKind.ColonToken);
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestSwitchStatementWithNullableTypeInPattern3()
+ {
+ UsingStatement("""
+ switch (obj)
+ {
+ case Type? when x > 0:
+ break;
+ }
+ """);
+
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestSwitchStatementWithNullableTypeInPattern4()
+ {
+ UsingStatement("""
+ switch (obj)
+ {
+ case Type? varName when x > 0:
+ break;
+ }
+ """);
+
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "varName");
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestSwitchStatementWithNullableTypeInPattern5()
+ {
+ UsingStatement("""
+ switch (obj)
+ {
+ case (Type? when) when x > 0:
+ break;
+ }
+ """);
+
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.ParenthesizedPattern);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "when");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
private sealed class TokenAndTriviaWalker : CSharpSyntaxWalker
{
public int Tokens;
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs
index 0f33ab868b05d..77f90db34eb36 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/SwitchExpressionParsingTests.cs
@@ -4231,4 +4231,658 @@ public void TestIncompleteSwitchExpression()
}
EOF();
}
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern1()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? => 1
+ }
+ """);
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern1_Colon()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? : 1
+ }
+ """,
+ // (3,11): error CS1003: Syntax error, '=>' expected
+ // Type? : 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("=>").WithLocation(3, 11));
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ M(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern2()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? varName => 1
+ }
+ """,
+ // (3,9): error CS1003: Syntax error, '=>' expected
+ // Type? varName => 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(3, 9),
+ // (3,9): error CS1525: Invalid expression term '?'
+ // Type? varName => 1
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(3, 9),
+ // (3,23): error CS1003: Syntax error, ':' expected
+ // Type? varName => 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(3, 23),
+ // (3,23): error CS1525: Invalid expression term '}'
+ // Type? varName => 1
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(3, 23));
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ }
+ M(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.ConditionalExpression);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.SimpleLambdaExpression);
+ {
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.IdentifierToken, "varName");
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ M(SyntaxKind.ColonToken);
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern2_Colon()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? varName : 1
+ }
+ """,
+ // (3,9): error CS1003: Syntax error, '=>' expected
+ // Type? varName : 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(3, 9),
+ // (3,9): error CS1525: Invalid expression term '?'
+ // Type? varName : 1
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(3, 9));
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ }
+ M(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.ConditionalExpression);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "varName");
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern3()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? when x > 0 => 1
+ }
+ """);
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern3_Colon()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? when x > 0 : 1
+ }
+ """,
+ // (3,22): error CS1003: Syntax error, '=>' expected
+ // Type? when x > 0 : 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("=>").WithLocation(3, 22));
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.TypePattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ M(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern4()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? varName when x > 0 => 1
+ }
+ """);
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "varName");
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern4_Colon()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ Type? varName when x > 0 : 1
+ }
+ """,
+ // (3,30): error CS1003: Syntax error, '=>' expected
+ // Type? varName when x > 0 : 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("=>").WithLocation(3, 30));
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "varName");
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ M(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern5()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ (Type? when) when x > 0 => 1
+ }
+ """);
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.ParenthesizedPattern);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "when");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestNullableTypeInPattern5_Colon()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ (Type? when) when x > 0 : 1
+ }
+ """,
+ // (3,29): error CS1003: Syntax error, '=>' expected
+ // (Type? when) when x > 0 : 1
+ Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments("=>").WithLocation(3, 29));
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.ParenthesizedPattern);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.NullableType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Type");
+ }
+ N(SyntaxKind.QuestionToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "when");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.GreaterThanExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "0");
+ }
+ }
+ }
+ M(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
+ public void TestConditionalExpressionAsPattern()
+ {
+ UsingExpression("""
+ obj switch
+ {
+ (flag ? a : b) => 1
+ }
+ """);
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "obj");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.ParenthesizedExpression);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.ConditionalExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "flag");
+ }
+ N(SyntaxKind.QuestionToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "a");
+ }
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "b");
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
}
diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/SymbolDeclaredCompilationEvent.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/SymbolDeclaredCompilationEvent.cs
index f03018973710f..381f4f62f51ff 100644
--- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/SymbolDeclaredCompilationEvent.cs
+++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/SymbolDeclaredCompilationEvent.cs
@@ -2,9 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Symbols;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics
{
@@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics
///
internal sealed class SymbolDeclaredCompilationEvent : CompilationEvent
{
- private readonly Lazy> _lazyCachedDeclaringReferences;
+ private ImmutableArray _lazyCachedDeclaringReferences;
public SymbolDeclaredCompilationEvent(
Compilation compilation,
@@ -25,7 +25,7 @@ public SymbolDeclaredCompilationEvent(
{
SymbolInternal = symbolInternal;
SemanticModelWithCachedBoundNodes = semanticModelWithCachedBoundNodes;
- _lazyCachedDeclaringReferences = new Lazy>(() => Symbol.DeclaringSyntaxReferences);
+ _lazyCachedDeclaringReferences = default(ImmutableArray);
}
public ISymbol Symbol => SymbolInternal.GetISymbol();
@@ -35,7 +35,16 @@ public SymbolDeclaredCompilationEvent(
public SemanticModel? SemanticModelWithCachedBoundNodes { get; }
// PERF: We avoid allocations in re-computing syntax references for declared symbol during event processing by caching them directly on this member.
- public ImmutableArray DeclaringSyntaxReferences => _lazyCachedDeclaringReferences.Value;
+ public ImmutableArray DeclaringSyntaxReferences
+ {
+ get
+ {
+ return InterlockedOperations.Initialize(
+ ref _lazyCachedDeclaringReferences,
+ static self => self.Symbol.DeclaringSyntaxReferences,
+ this);
+ }
+ }
public override string ToString()
{
diff --git a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs
index c3fcbfbd57629..9636bd3fbb871 100644
--- a/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs
+++ b/src/EditorFeatures/CSharp/AutomaticCompletion/AutomaticLineEnderCommandHandler.cs
@@ -28,6 +28,7 @@
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Host;
+using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.Editor.CSharp.AutomaticCompletion;
@@ -313,9 +314,10 @@ protected override void ModifySelectedNode(
SyntaxNode selectedNode,
bool addBrace,
int caretPosition,
+ StructuredAnalyzerConfigOptions fallbackOptions,
CancellationToken cancellationToken)
{
- var formattingOptions = args.SubjectBuffer.GetSyntaxFormattingOptions(EditorOptionsService, document.LanguageServices, explicitFormat: false);
+ var formattingOptions = args.SubjectBuffer.GetSyntaxFormattingOptions(EditorOptionsService, fallbackOptions, document.LanguageServices, explicitFormat: false);
// Add braces for the selected node
if (addBrace)
diff --git a/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs b/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs
index 4ad682630baff..76e1a337054ad 100644
--- a/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs
+++ b/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs
@@ -141,7 +141,7 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler,
if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(s_fileScopedNamespacePreferenceOption, (CompilationUnitSyntax)parsedDocument.Root, namespaceDecl, forAnalyzer: true, LanguageVersion.CSharp10))
return default;
- var formattingOptions = subjectBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.Services, explicitFormat: false);
+ var formattingOptions = subjectBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, explicitFormat: false);
return ConvertNamespaceTransform.ConvertNamespaceDeclaration(parsedDocument, namespaceDecl, formattingOptions, cancellationToken);
}
}
diff --git a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs
index 0cb940aba6795..c51e8dd9b7c3f 100644
--- a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs
+++ b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs
@@ -86,7 +86,7 @@ public Task> GetFormattingChangesAsync(
CancellationToken cancellationToken)
{
var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
- var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: true);
+ var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), parsedDocument.LanguageServices, explicitFormat: true);
var span = textSpan ?? new TextSpan(0, parsedDocument.Root.FullSpan.Length);
var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(parsedDocument.Root, span);
@@ -97,7 +97,7 @@ public Task> GetFormattingChangesAsync(
public Task> GetFormattingChangesOnPasteAsync(Document document, ITextBuffer textBuffer, TextSpan textSpan, CancellationToken cancellationToken)
{
var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
- var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: true);
+ var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), parsedDocument.LanguageServices, explicitFormat: true);
var service = parsedDocument.LanguageServices.GetRequiredService();
return Task.FromResult(service.GetFormattingChangesOnPaste(parsedDocument, textSpan, options, cancellationToken));
}
@@ -112,7 +112,7 @@ public Task> GetFormattingChangesAsync(Document docum
if (service.ShouldFormatOnTypedCharacter(parsedDocument, typedChar, position, cancellationToken))
{
- var indentationOptions = textBuffer.GetIndentationOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: false);
+ var indentationOptions = textBuffer.GetIndentationOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), parsedDocument.LanguageServices, explicitFormat: false);
return Task.FromResult(service.GetFormattingChangesOnTypedCharacter(parsedDocument, position, indentationOptions, cancellationToken));
}
diff --git a/src/EditorFeatures/CSharp/RawStringLiteral/RawStringLiteralCommandHandler_Return.cs b/src/EditorFeatures/CSharp/RawStringLiteral/RawStringLiteralCommandHandler_Return.cs
index 8e163ffa7583d..0c66d57a8fa48 100644
--- a/src/EditorFeatures/CSharp/RawStringLiteral/RawStringLiteralCommandHandler_Return.cs
+++ b/src/EditorFeatures/CSharp/RawStringLiteral/RawStringLiteralCommandHandler_Return.cs
@@ -98,7 +98,7 @@ SyntaxKind.InterpolatedSingleLineRawStringStartToken or
return false;
}
- var indentationOptions = subjectBuffer.GetIndentationOptions(_editorOptionsService, document.Project.Services, explicitFormat: false);
+ var indentationOptions = subjectBuffer.GetIndentationOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, explicitFormat: false);
var indentation = token.GetPreferredIndentation(parsedDocument, indentationOptions, cancellationToken);
var newLine = indentationOptions.FormattingOptions.NewLine;
diff --git a/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs b/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs
index aa0819766aa6e..d5cab6ad4a0d8 100644
--- a/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs
+++ b/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs
@@ -80,7 +80,7 @@ public bool ExecuteCommandWorker(ReturnKeyCommandArgs args, CancellationToken ca
return false;
var parsedDocument = ParsedDocument.CreateSynchronously(document, CancellationToken.None);
- var indentationOptions = subjectBuffer.GetIndentationOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: false);
+ var indentationOptions = subjectBuffer.GetIndentationOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), parsedDocument.LanguageServices, explicitFormat: false);
// We now go through the verified string literals and split each of them.
// The list of spans is traversed in reverse order so we do not have to
diff --git a/src/EditorFeatures/CSharp/StringCopyPaste/StringCopyPasteCommandHandler.cs b/src/EditorFeatures/CSharp/StringCopyPaste/StringCopyPasteCommandHandler.cs
index 592925bdef8ac..d1f7077462368 100644
--- a/src/EditorFeatures/CSharp/StringCopyPaste/StringCopyPasteCommandHandler.cs
+++ b/src/EditorFeatures/CSharp/StringCopyPaste/StringCopyPasteCommandHandler.cs
@@ -8,6 +8,7 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.StringCopyPaste;
@@ -186,7 +187,7 @@ ImmutableArray GetEdits(CancellationToken cancellationToken)
{
var newLine = textView.Options.GetNewLineCharacter();
var indentationWhitespace = DetermineIndentationWhitespace(
- parsedDocumentBeforePaste, subjectBuffer, snapshotBeforePaste.AsText(), stringExpressionBeforePaste, cancellationToken);
+ parsedDocumentBeforePaste, subjectBuffer, snapshotBeforePaste.AsText(), stringExpressionBeforePaste, documentBeforePaste.Project.GetFallbackAnalyzerOptions(), cancellationToken);
// See if this is a paste of the last copy that we heard about.
var edits = TryGetEditsFromKnownCopySource(newLine, indentationWhitespace);
@@ -235,6 +236,7 @@ private string DetermineIndentationWhitespace(
ITextBuffer textBuffer,
SourceText textBeforePaste,
ExpressionSyntax stringExpressionBeforePaste,
+ StructuredAnalyzerConfigOptions fallbackOptions,
CancellationToken cancellationToken)
{
// Only raw strings care about indentation. Don't bother computing if we don't need it.
@@ -252,7 +254,7 @@ private string DetermineIndentationWhitespace(
// Otherwise, we have a single-line raw string. Determine the default indentation desired here.
// We'll use that if we have to convert this single-line raw string to a multi-line one.
- var indentationOptions = textBuffer.GetIndentationOptions(_editorOptionsService, documentBeforePaste.LanguageServices, explicitFormat: false);
+ var indentationOptions = textBuffer.GetIndentationOptions(_editorOptionsService, fallbackOptions, documentBeforePaste.LanguageServices, explicitFormat: false);
return stringExpressionBeforePaste.GetFirstToken().GetPreferredIndentation(documentBeforePaste, indentationOptions, cancellationToken);
}
diff --git a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs
index a4ab425197cd9..df7f3b889c6ed 100644
--- a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs
+++ b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs
@@ -21,6 +21,7 @@
using Microsoft.CodeAnalysis.Diagnostics.CSharp;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Editor.UnitTests;
+using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
@@ -886,10 +887,12 @@ private protected static async Task AssertCodeCleanupResult(string expected, str
using var workspace = EditorTestWorkspace.CreateCSharp(code, composition: EditorTestCompositions.EditorFeaturesWpf);
// must set global options since incremental analyzer infra reads from global options
- var globalOptions = workspace.GlobalOptions;
- globalOptions.SetGlobalOption(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.CSharp, separateUsingGroups);
- globalOptions.SetGlobalOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp, systemUsingsFirst);
- globalOptions.SetGlobalOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, preferredImportPlacement);
+ workspace.SetAnalyzerFallbackAndGlobalOptions(new OptionsCollection(LanguageNames.CSharp)
+ {
+ { GenerationOptions.SeparateImportDirectiveGroups, separateUsingGroups },
+ { GenerationOptions.PlaceSystemNamespaceFirst, systemUsingsFirst },
+ { CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, preferredImportPlacement },
+ });
var solution = workspace.CurrentSolution.WithAnalyzerReferences(new[]
{
@@ -923,7 +926,7 @@ private protected static async Task AssertCodeCleanupResult(string expected, str
enabledDiagnostics = VisualStudio.LanguageServices.Implementation.CodeCleanup.AbstractCodeCleanUpFixer.AdjustDiagnosticOptions(enabledDiagnostics, enabledFixIdsFilter);
var newDoc = await codeCleanupService.CleanupAsync(
- document, enabledDiagnostics, CodeAnalysisProgress.None, globalOptions.CreateProvider(), CancellationToken.None);
+ document, enabledDiagnostics, CodeAnalysisProgress.None, workspace.GlobalOptions.CreateProvider(), CancellationToken.None);
var actual = await newDoc.GetTextAsync();
diff --git a/src/EditorFeatures/Core/AutomaticCompletion/AbstractAutomaticLineEnderCommandHandler.cs b/src/EditorFeatures/Core/AutomaticCompletion/AbstractAutomaticLineEnderCommandHandler.cs
index 9515c1e4ed9c9..04a34b24d239b 100644
--- a/src/EditorFeatures/Core/AutomaticCompletion/AbstractAutomaticLineEnderCommandHandler.cs
+++ b/src/EditorFeatures/Core/AutomaticCompletion/AbstractAutomaticLineEnderCommandHandler.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
+using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
@@ -61,7 +62,7 @@ protected AbstractAutomaticLineEnderCommandHandler(
///
/// Add or remove the braces for .
///
- protected abstract void ModifySelectedNode(AutomaticLineEnderCommandArgs args, ParsedDocument document, SyntaxNode selectedNode, bool addBrace, int caretPosition, CancellationToken cancellationToken);
+ protected abstract void ModifySelectedNode(AutomaticLineEnderCommandArgs args, ParsedDocument document, SyntaxNode selectedNode, bool addBrace, int caretPosition, StructuredAnalyzerConfigOptions fallbackOptions, CancellationToken cancellationToken);
///
/// Get the syntax node needs add/remove braces.
@@ -131,7 +132,7 @@ public void ExecuteCommand(AutomaticLineEnderCommandArgs args, Action nextHandle
{
var (selectedNode, addBrace) = selectNodeAndOperationKind.Value;
using var transaction = args.TextView.CreateEditTransaction(EditorFeaturesResources.Automatic_Line_Ender, _undoRegistry, _editorOperationsFactoryService);
- ModifySelectedNode(args, parsedDocument, selectedNode, addBrace, caretPosition, cancellationToken);
+ ModifySelectedNode(args, parsedDocument, selectedNode, addBrace, caretPosition, document.Project.GetFallbackAnalyzerOptions(), cancellationToken);
NextAction(operations, nextHandler);
transaction.Complete();
return;
@@ -142,7 +143,7 @@ public void ExecuteCommand(AutomaticLineEnderCommandArgs args, Action nextHandle
if (endingInsertionPosition != null)
{
using var transaction = args.TextView.CreateEditTransaction(EditorFeaturesResources.Automatic_Line_Ender, _undoRegistry, _editorOperationsFactoryService);
- var formattingOptions = args.SubjectBuffer.GetSyntaxFormattingOptions(EditorOptionsService, parsedDocument.LanguageServices, explicitFormat: false);
+ var formattingOptions = args.SubjectBuffer.GetSyntaxFormattingOptions(EditorOptionsService, document.Project.GetFallbackAnalyzerOptions(), parsedDocument.LanguageServices, explicitFormat: false);
InsertEnding(args.TextView, args.SubjectBuffer, parsedDocument, endingInsertionPosition.Value, caretPosition, formattingOptions, cancellationToken);
NextAction(operations, nextHandler);
transaction.Complete();
diff --git a/src/EditorFeatures/Core/AutomaticCompletion/BraceCompletionSessionProvider.BraceCompletionSession.cs b/src/EditorFeatures/Core/AutomaticCompletion/BraceCompletionSessionProvider.BraceCompletionSession.cs
index 3d520a1dc087d..3d9c496a7b667 100644
--- a/src/EditorFeatures/Core/AutomaticCompletion/BraceCompletionSessionProvider.BraceCompletionSession.cs
+++ b/src/EditorFeatures/Core/AutomaticCompletion/BraceCompletionSessionProvider.BraceCompletionSession.cs
@@ -8,6 +8,7 @@
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.BraceCompletion;
+using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.ErrorReporting;
@@ -105,7 +106,7 @@ private bool TryStart(CancellationToken cancellationToken)
}
var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
- var context = GetBraceCompletionContext(parsedDocument);
+ var context = GetBraceCompletionContext(parsedDocument, document.Project.GetFallbackAnalyzerOptions());
// Note: completes synchronously unless Semantic Model is needed to determine the result:
if (!_service.HasBraceCompletionAsync(context, document, cancellationToken).WaitAndGetResult(cancellationToken))
@@ -125,7 +126,7 @@ private bool TryStart(CancellationToken cancellationToken)
if (TryGetBraceCompletionContext(out var contextAfterStart, cancellationToken))
{
- var indentationOptions = SubjectBuffer.GetIndentationOptions(_editorOptionsService, contextAfterStart.Document.LanguageServices, explicitFormat: false);
+ var indentationOptions = SubjectBuffer.GetIndentationOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), contextAfterStart.Document.LanguageServices, explicitFormat: false);
var changesAfterStart = _service.GetTextChangesAfterCompletion(contextAfterStart, indentationOptions, cancellationToken);
if (changesAfterStart != null)
{
@@ -283,7 +284,7 @@ public void PostReturn()
return;
}
- var indentationOptions = SubjectBuffer.GetIndentationOptions(_editorOptionsService, context.Document.LanguageServices, explicitFormat: false);
+ var indentationOptions = SubjectBuffer.GetIndentationOptions(_editorOptionsService, context.FallbackOptions, context.Document.LanguageServices, explicitFormat: false);
var changesAfterReturn = _service.GetTextChangeAfterReturn(context, indentationOptions, CancellationToken.None);
if (changesAfterReturn != null)
{
@@ -397,11 +398,11 @@ private bool TryGetBraceCompletionContext(out BraceCompletionContext context, Ca
return false;
}
- context = GetBraceCompletionContext(ParsedDocument.CreateSynchronously(document, cancellationToken));
+ context = GetBraceCompletionContext(ParsedDocument.CreateSynchronously(document, cancellationToken), document.Project.GetFallbackAnalyzerOptions());
return true;
}
- private BraceCompletionContext GetBraceCompletionContext(ParsedDocument document)
+ private BraceCompletionContext GetBraceCompletionContext(ParsedDocument document, StructuredAnalyzerConfigOptions fallbackOptions)
{
_threadingContext.ThrowIfNotOnUIThread();
var snapshot = SubjectBuffer.CurrentSnapshot;
@@ -411,7 +412,7 @@ private BraceCompletionContext GetBraceCompletionContext(ParsedDocument document
// The user is actively typing so the caret position should not be null.
var caretPosition = this.GetCaretPosition().Value.Position;
- return new BraceCompletionContext(document, openingSnapshotPoint, closingSnapshotPoint, caretPosition);
+ return new BraceCompletionContext(document, fallbackOptions, openingSnapshotPoint, closingSnapshotPoint, caretPosition);
}
private void ApplyBraceCompletionResult(BraceCompletionResult result)
diff --git a/src/EditorFeatures/Core/CommentSelection/AbstractCommentSelectionBase.cs b/src/EditorFeatures/Core/CommentSelection/AbstractCommentSelectionBase.cs
index 7609d2fc0377f..57a7ca49ceefa 100644
--- a/src/EditorFeatures/Core/CommentSelection/AbstractCommentSelectionBase.cs
+++ b/src/EditorFeatures/Core/CommentSelection/AbstractCommentSelectionBase.cs
@@ -149,7 +149,7 @@ private void ApplyEdits(Document document, ITextView textView, ITextBuffer subje
var oldSyntaxTree = document.GetSyntaxTreeSynchronously(cancellationToken);
var newRoot = oldSyntaxTree.WithChangedText(newText).GetRoot(cancellationToken);
- var formattingOptions = subjectBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.Services, explicitFormat: false);
+ var formattingOptions = subjectBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, explicitFormat: false);
var formattingSpans = trackingSnapshotSpans.Select(change => CommonFormattingHelpers.GetFormattingSpan(newRoot, change.Span.ToTextSpan()));
var formattedChanges = Formatter.GetFormattedTextChanges(newRoot, formattingSpans, document.Project.Solution.Services, formattingOptions, rules: default, cancellationToken);
diff --git a/src/EditorFeatures/Core/Options/EditorAnalyzerConfigOptions.cs b/src/EditorFeatures/Core/Options/EditorAnalyzerConfigOptions.cs
index 89086b1131b26..49a55053e7043 100644
--- a/src/EditorFeatures/Core/Options/EditorAnalyzerConfigOptions.cs
+++ b/src/EditorFeatures/Core/Options/EditorAnalyzerConfigOptions.cs
@@ -61,6 +61,6 @@ private static bool IsLowercase(string str)
internal static partial class EditorOptionsExtensions
{
- public static StructuredAnalyzerConfigOptions ToAnalyzerConfigOptions(this IEditorOptions editorOptions)
- => StructuredAnalyzerConfigOptions.Create(new EditorAnalyzerConfigOptions(editorOptions));
+ public static StructuredAnalyzerConfigOptions ToAnalyzerConfigOptions(this IEditorOptions editorOptions, StructuredAnalyzerConfigOptions fallbackOptions)
+ => StructuredAnalyzerConfigOptions.Create(new EditorAnalyzerConfigOptions(editorOptions), fallbackOptions);
}
diff --git a/src/EditorFeatures/Core/Options/TextBufferOptionProviders.cs b/src/EditorFeatures/Core/Options/TextBufferOptionProviders.cs
index ce61da12f9add..50ab0fb90a025 100644
--- a/src/EditorFeatures/Core/Options/TextBufferOptionProviders.cs
+++ b/src/EditorFeatures/Core/Options/TextBufferOptionProviders.cs
@@ -40,23 +40,22 @@ private static LineFormattingOptions GetLineFormattingOptionsImpl(ITextBuffer te
};
}
- public static SyntaxFormattingOptions GetSyntaxFormattingOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, LanguageServices languageServices, bool explicitFormat)
- => GetSyntaxFormattingOptionsImpl(textBuffer, optionsProvider.Factory.GetOptions(textBuffer), optionsProvider.IndentationManager, optionsProvider.GlobalOptions, languageServices, explicitFormat);
+ public static SyntaxFormattingOptions GetSyntaxFormattingOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, StructuredAnalyzerConfigOptions fallbackOptions, LanguageServices languageServices, bool explicitFormat)
+ => GetSyntaxFormattingOptionsImpl(textBuffer, optionsProvider.Factory.GetOptions(textBuffer), fallbackOptions, optionsProvider.IndentationManager, languageServices, explicitFormat);
- private static SyntaxFormattingOptions GetSyntaxFormattingOptionsImpl(ITextBuffer textBuffer, IEditorOptions editorOptions, IIndentationManagerService indentationManager, IGlobalOptionService globalOptions, LanguageServices languageServices, bool explicitFormat)
+ private static SyntaxFormattingOptions GetSyntaxFormattingOptionsImpl(ITextBuffer textBuffer, IEditorOptions editorOptions, StructuredAnalyzerConfigOptions fallbackOptions, IIndentationManagerService indentationManager, LanguageServices languageServices, bool explicitFormat)
{
- var configOptions = editorOptions.ToAnalyzerConfigOptions();
- var fallbackOptions = globalOptions.GetSyntaxFormattingOptions(languageServices);
- var options = configOptions.GetSyntaxFormattingOptions(languageServices, fallbackOptions);
+ var configOptions = editorOptions.ToAnalyzerConfigOptions(fallbackOptions);
+ var options = configOptions.GetSyntaxFormattingOptions(languageServices);
var lineFormattingOptions = GetLineFormattingOptionsImpl(textBuffer, editorOptions, indentationManager, explicitFormat);
return options with { LineFormatting = lineFormattingOptions };
}
- public static IndentationOptions GetIndentationOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, LanguageServices languageServices, bool explicitFormat)
+ public static IndentationOptions GetIndentationOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, StructuredAnalyzerConfigOptions fallbackOptions, LanguageServices languageServices, bool explicitFormat)
{
var editorOptions = optionsProvider.Factory.GetOptions(textBuffer);
- var formattingOptions = GetSyntaxFormattingOptionsImpl(textBuffer, editorOptions, optionsProvider.IndentationManager, optionsProvider.GlobalOptions, languageServices, explicitFormat);
+ var formattingOptions = GetSyntaxFormattingOptionsImpl(textBuffer, editorOptions, fallbackOptions, optionsProvider.IndentationManager, languageServices, explicitFormat);
return new IndentationOptions(formattingOptions)
{
@@ -66,21 +65,19 @@ public static IndentationOptions GetIndentationOptions(this ITextBuffer textBuff
};
}
- public static AddImportPlacementOptions GetAddImportPlacementOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, LanguageServices languageServices, bool allowInHiddenRegions)
+ public static AddImportPlacementOptions GetAddImportPlacementOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, StructuredAnalyzerConfigOptions fallbackOptions, LanguageServices languageServices, bool allowInHiddenRegions)
{
var editorOptions = optionsProvider.Factory.GetOptions(textBuffer);
- var configOptions = editorOptions.ToAnalyzerConfigOptions();
- var fallbackOptions = optionsProvider.GlobalOptions.GetAddImportPlacementOptions(languageServices);
- return configOptions.GetAddImportPlacementOptions(languageServices, allowInHiddenRegions, fallbackOptions);
+ var configOptions = editorOptions.ToAnalyzerConfigOptions(fallbackOptions);
+ return configOptions.GetAddImportPlacementOptions(languageServices, allowInHiddenRegions, fallbackOptions: null);
}
- public static CodeCleanupOptions GetCodeCleanupOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, LanguageServices languageServices, bool explicitFormat, bool allowImportsInHiddenRegions)
+ public static CodeCleanupOptions GetCodeCleanupOptions(this ITextBuffer textBuffer, EditorOptionsService optionsProvider, StructuredAnalyzerConfigOptions fallbackOptions, LanguageServices languageServices, bool explicitFormat, bool allowImportsInHiddenRegions)
{
var editorOptions = optionsProvider.Factory.GetOptions(textBuffer);
- var configOptions = editorOptions.ToAnalyzerConfigOptions();
- var fallbackOptions = optionsProvider.GlobalOptions.GetCodeCleanupOptions(languageServices);
+ var configOptions = editorOptions.ToAnalyzerConfigOptions(fallbackOptions);
- var options = configOptions.GetCodeCleanupOptions(languageServices, allowImportsInHiddenRegions, fallbackOptions);
+ var options = configOptions.GetCodeCleanupOptions(languageServices, allowImportsInHiddenRegions, fallbackOptions: null);
var lineFormattingOptions = GetLineFormattingOptionsImpl(textBuffer, editorOptions, optionsProvider.IndentationManager, explicitFormat);
return options with { FormattingOptions = options.FormattingOptions with { LineFormatting = lineFormattingOptions } };
diff --git a/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs b/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs
index 6e14ab4d415b6..eb78e0649ee55 100644
--- a/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs
+++ b/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs
@@ -187,7 +187,7 @@ public bool ExecuteCommand(SortAndRemoveUnnecessaryImportsCommandArgs args, Comm
async (document, cancellationToken) =>
{
var formattingOptions = document.SupportsSyntaxTree
- ? await document.GetSyntaxFormattingOptionsAsync(_globalOptions, cancellationToken).ConfigureAwait(false)
+ ? await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false)
: null;
var removeImportsService = document.GetRequiredLanguageService();
diff --git a/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs b/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs
index e9e3c5b7e0c9b..5b5b5b540f502 100644
--- a/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs
+++ b/src/EditorFeatures/Core/Shared/Extensions/ITextSnapshotExtensions.cs
@@ -39,7 +39,7 @@ public static void FormatAndApplyToBuffer(
var formatter = document.GetRequiredLanguageService();
- var options = textBuffer.GetSyntaxFormattingOptions(editorOptionsService, document.Project.Services, explicitFormat: false);
+ var options = textBuffer.GetSyntaxFormattingOptions(editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, explicitFormat: false);
var result = formatter.GetFormattingResult(documentSyntax.Root, [span], options, rules, cancellationToken);
var changes = result.GetTextChanges(cancellationToken);
diff --git a/src/EditorFeatures/Core/SmartIndent/SmartIndent.cs b/src/EditorFeatures/Core/SmartIndent/SmartIndent.cs
index 335d0519d9661..7d573c4db7f21 100644
--- a/src/EditorFeatures/Core/SmartIndent/SmartIndent.cs
+++ b/src/EditorFeatures/Core/SmartIndent/SmartIndent.cs
@@ -42,7 +42,7 @@ public void Dispose()
if (newService == null)
return null;
- var indentationOptions = line.Snapshot.TextBuffer.GetIndentationOptions(_editorOptionsService, document.Project.Services, explicitFormat: false);
+ var indentationOptions = line.Snapshot.TextBuffer.GetIndentationOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, explicitFormat: false);
var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
var result = newService.GetIndentation(parsedDocument, line.LineNumber, indentationOptions, cancellationToken);
return result.GetIndentation(_textView, line);
diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf
index 97480af8edaa0..62c746509551f 100644
--- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf
+++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf
@@ -29,17 +29,17 @@
Copilot
- Copilot
+ Copilot
Copilot thinking...
- Copilot thinking...
+ Copilot 思考中...
Describe with Copilot
- Describe with Copilot
+ 使用 Copilot 加以描述
@@ -79,7 +79,7 @@
Generate summary with Copilot (might be inaccurate)
- Generate summary with Copilot (might be inaccurate)
+ 使用 Copilot 產生摘要 (可能不準確)
@@ -644,7 +644,7 @@
'{0}' intercepted locations
- '{0}' intercepted locations
+ '{0}' 已攔截的位置
diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs
index ec9853314c97e..9c7a3734976ca 100644
--- a/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs
+++ b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs
@@ -38,7 +38,7 @@ public static ChangeSignatureTestState Create(string markup, string languageName
_ => throw new ArgumentException("Invalid language name.")
};
- options?.SetGlobalOptions(workspace.GlobalOptions);
+ workspace.SetAnalyzerFallbackAndGlobalOptions(options);
return new ChangeSignatureTestState(workspace);
}
diff --git a/src/EditorFeatures/TestUtilities/AutomaticCompletion/AbstractAutomaticBraceCompletionTests.cs b/src/EditorFeatures/TestUtilities/AutomaticCompletion/AbstractAutomaticBraceCompletionTests.cs
index d1b2607fc1a28..034d50afdbfaa 100644
--- a/src/EditorFeatures/TestUtilities/AutomaticCompletion/AbstractAutomaticBraceCompletionTests.cs
+++ b/src/EditorFeatures/TestUtilities/AutomaticCompletion/AbstractAutomaticBraceCompletionTests.cs
@@ -144,6 +144,8 @@ internal static void Type(IBraceCompletionSession session, string text)
internal static Holder CreateSession(EditorTestWorkspace workspace, char opening, char closing, OptionsCollection globalOptions = null)
{
+ workspace.SetAnalyzerFallbackAndGlobalOptions(globalOptions);
+
var document = workspace.Documents.First();
var provider = Assert.IsType(workspace.GetService());
@@ -151,7 +153,6 @@ internal static Holder CreateSession(EditorTestWorkspace workspace, char opening
var openingPoint = new SnapshotPoint(document.GetTextBuffer().CurrentSnapshot, document.CursorPosition.Value);
var textView = document.GetTextView();
- globalOptions?.SetGlobalOptions(workspace.GlobalOptions);
workspace.GlobalOptions.SetEditorOptions(textView.Options.GlobalOptions, document.Project.Language);
if (provider.TryCreateSession(textView, openingPoint, opening, closing, out var session))
diff --git a/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs b/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs
index e10dfa5df6db2..c466125a9c7ac 100644
--- a/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs
+++ b/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs
@@ -42,7 +42,7 @@ public static ExtractInterfaceTestState Create(
? EditorTestWorkspace.CreateCSharp(markup, composition: Composition, compilationOptions: compilationOptions, parseOptions: parseOptions)
: EditorTestWorkspace.CreateVisualBasic(markup, composition: Composition, compilationOptions: compilationOptions, parseOptions: parseOptions);
- options?.SetGlobalOptions(workspace.GlobalOptions);
+ workspace.SetAnalyzerFallbackAndGlobalOptions(options);
return new ExtractInterfaceTestState(workspace);
}
diff --git a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs
index 8334f80402998..f99a17ee49a6d 100644
--- a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs
+++ b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs
@@ -131,7 +131,7 @@ private protected void AssertFormatWithView(string expectedWithMarker, string co
{
using var workspace = CreateWorkspace(codeWithMarker, parseOptions);
- options?.SetGlobalOptions(workspace.GlobalOptions);
+ workspace.SetAnalyzerFallbackAndGlobalOptions(options);
// set up caret position
var testDocument = workspace.Documents.Single();
@@ -200,7 +200,7 @@ private protected async Task AssertFormatAsync(string expected, string code, IEn
var formattingService = document.GetRequiredLanguageService();
var formattingOptions = (options != null)
- ? formattingService.GetFormattingOptions(options, fallbackOptions: null)
+ ? formattingService.GetFormattingOptions(options)
: formattingService.DefaultOptions;
ImmutableArray rules = [formattingRuleProvider.CreateRule(documentSyntax, 0), .. Formatter.GetDefaultFormattingRules(document)];
@@ -286,7 +286,7 @@ protected static void AssertFormatOnArbitraryNode(SyntaxNode node, string expect
{
using var workspace = new AdhocWorkspace();
var formattingService = workspace.Services.GetLanguageServices(node.Language).GetRequiredService();
- var options = formattingService.GetFormattingOptions(StructuredAnalyzerConfigOptions.Empty, fallbackOptions: null);
+ var options = formattingService.GetFormattingOptions(StructuredAnalyzerConfigOptions.Empty);
var result = Formatter.Format(node, workspace.Services.SolutionServices, options, CancellationToken.None);
var actual = result.GetText().ToString();
diff --git a/src/EditorFeatures/VisualBasic/AutomaticCompletion/AutomaticLineEnderCommandHandler.vb b/src/EditorFeatures/VisualBasic/AutomaticCompletion/AutomaticLineEnderCommandHandler.vb
index 3ff2273657ce8..aeae57260ace0 100644
--- a/src/EditorFeatures/VisualBasic/AutomaticCompletion/AutomaticLineEnderCommandHandler.vb
+++ b/src/EditorFeatures/VisualBasic/AutomaticCompletion/AutomaticLineEnderCommandHandler.vb
@@ -5,6 +5,7 @@
Imports System.ComponentModel.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis.AutomaticCompletion
+Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.Options
@@ -46,7 +47,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.AutomaticCompletion
Return False
End Function
- Protected Overrides Sub ModifySelectedNode(args As AutomaticLineEnderCommandArgs, document As ParsedDocument, selectedNode As SyntaxNode, addBrace As Boolean, caretPosition As Integer, cancellationToken As CancellationToken)
+ Protected Overrides Sub ModifySelectedNode(args As AutomaticLineEnderCommandArgs, document As ParsedDocument, selectedNode As SyntaxNode, addBrace As Boolean, caretPosition As Integer, fallbackOptions As StructuredAnalyzerConfigOptions, cancellationToken As CancellationToken)
End Sub
Protected Overrides Function GetValidNodeToModifyBraces(document As ParsedDocument, caretPosition As Integer, cancellationToken As CancellationToken) As (SyntaxNode, Boolean)?
diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb
index b7e5fc83c4665..7d593f2862e37 100644
--- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb
+++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb
@@ -140,7 +140,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration
Return p.Name = PredefinedCodeCleanupProviderNames.NormalizeModifiersOrOperators
End Function)
- Dim options = buffer.GetCodeCleanupOptions(_editorOptionsService, document.Project.Services, explicitFormat:=False, allowImportsInHiddenRegions:=document.AllowImportsInHiddenRegions())
+ Dim options = buffer.GetCodeCleanupOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, explicitFormat:=False, allowImportsInHiddenRegions:=document.AllowImportsInHiddenRegions())
Dim cleanDocument = CodeCleaner.CleanupAsync(document, GetSpanToCleanup(statement), Options, codeCleanups, cancellationToken:=cancellationToken).WaitAndGetResult(cancellationToken)
Dim changes = cleanDocument.GetTextChangesAsync(document, cancellationToken).WaitAndGetResult(cancellationToken)
diff --git a/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb b/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb
index 6fa92b52053b2..89db5228db666 100644
--- a/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb
+++ b/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb
@@ -72,7 +72,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit
End If
' create commit formatting cleanup provider that has line commit specific behavior
- Dim cleanupOptions = buffer.GetCodeCleanupOptions(_editorOptionsService, document.Project.Services, isExplicitFormat, allowImportsInHiddenRegions:=document.AllowImportsInHiddenRegions())
+ Dim cleanupOptions = buffer.GetCodeCleanupOptions(_editorOptionsService, document.Project.GetFallbackAnalyzerOptions(), document.Project.Services, isExplicitFormat, allowImportsInHiddenRegions:=document.AllowImportsInHiddenRegions())
Dim commitFormattingCleanup = GetCommitFormattingCleanupProvider(
document.Id,
document.Project.Services,
diff --git a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb
index 3bd42bc2532c8..b98364b8ffbf6 100644
--- a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb
+++ b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb
@@ -61,7 +61,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar
End If
Dim simplifierOptions = Await newDocument.GetSimplifierOptionsAsync(cancellationToken).ConfigureAwait(False)
- Dim formattingOptions = Await newDocument.GetSyntaxFormattingOptionsAsync(globalOptions, cancellationToken).ConfigureAwait(False)
+ Dim formattingOptions = Await newDocument.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(False)
newDocument = Await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, simplifierOptions, cancellationToken).ConfigureAwait(False)
diff --git a/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs
index 3e001256b88f8..fb7e0ac174695 100644
--- a/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs
+++ b/src/Features/CSharp/Portable/ConvertToRawString/ConvertStringToRawStringCodeRefactoringProvider.cs
@@ -77,7 +77,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return;
var options = context.Options;
- var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(options, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var parsedDocument = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);
if (!CanConvert(parsedDocument, parentExpression, formattingOptions, out var convertParams, out var provider, cancellationToken))
@@ -90,7 +90,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
context.RegisterRefactoring(
CodeAction.Create(
CSharpFeaturesResources.Convert_to_raw_string,
- cancellationToken => UpdateDocumentAsync(document, parentExpression, ConvertToRawKind.SingleLine, options, provider, cancellationToken),
+ cancellationToken => UpdateDocumentAsync(document, parentExpression, ConvertToRawKind.SingleLine, provider, cancellationToken),
s_kindToEquivalenceKeyMap[ConvertToRawKind.SingleLine],
priority),
token.Span);
@@ -100,7 +100,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
context.RegisterRefactoring(
CodeAction.Create(
CSharpFeaturesResources.Convert_to_raw_string,
- cancellationToken => UpdateDocumentAsync(document, parentExpression, ConvertToRawKind.MultiLineIndented, options, provider, cancellationToken),
+ cancellationToken => UpdateDocumentAsync(document, parentExpression, ConvertToRawKind.MultiLineIndented, provider, cancellationToken),
s_kindToEquivalenceKeyMap[ConvertToRawKind.MultiLineIndented],
priority),
token.Span);
@@ -110,7 +110,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
context.RegisterRefactoring(
CodeAction.Create(
CSharpFeaturesResources.without_leading_whitespace_may_change_semantics,
- cancellationToken => UpdateDocumentAsync(document, parentExpression, ConvertToRawKind.MultiLineWithoutLeadingWhitespace, options, provider, cancellationToken),
+ cancellationToken => UpdateDocumentAsync(document, parentExpression, ConvertToRawKind.MultiLineWithoutLeadingWhitespace, provider, cancellationToken),
s_kindToEquivalenceKeyMap[ConvertToRawKind.MultiLineWithoutLeadingWhitespace],
priority),
token.Span);
@@ -122,11 +122,10 @@ private static async Task UpdateDocumentAsync(
Document document,
ExpressionSyntax expression,
ConvertToRawKind kind,
- CodeActionOptionsProvider optionsProvider,
IConvertStringProvider provider,
CancellationToken cancellationToken)
{
- var options = await document.GetSyntaxFormattingOptionsAsync(optionsProvider, cancellationToken).ConfigureAwait(false);
+ var options = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var parsedDocument = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);
@@ -146,7 +145,7 @@ protected override async Task FixAllAsync(
Debug.Assert(equivalenceKey != null);
var kind = s_kindToEquivalenceKeyMap[equivalenceKey];
- var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(optionsProvider, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var parsedDocument = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);
foreach (var fixSpan in fixAllSpans)
diff --git a/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs
index c7892f461d62a..bb0d0296fc386 100644
--- a/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs
+++ b/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs
@@ -74,7 +74,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
if (parameterNameParts.BaseName == "")
return;
- var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var fieldOrProperty = TryFindMatchingUninitializedFieldOrPropertySymbol();
var refactorings = fieldOrProperty == null
diff --git a/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs
index 5ba4d33c0368f..6569ef7bdd066 100644
--- a/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs
+++ b/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs
@@ -95,7 +95,7 @@ protected override async Task AddIndentationToDocumentAsync(Document d
{
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var syntaxFormattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false);
+ var syntaxFormattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var indentationString = CSharpSnippetHelpers.GetBlockLikeIndentationString(document, typeDeclaration.OpenBraceToken.SpanStart, syntaxFormattingOptions, cancellationToken);
var newTypeDeclaration = typeDeclaration.WithCloseBraceToken(
diff --git a/src/Features/CSharp/Portable/Snippets/CSharpIntMainSnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/CSharpIntMainSnippetProvider.cs
index 8016a03df0e8e..47f4954c017fa 100644
--- a/src/Features/CSharp/Portable/Snippets/CSharpIntMainSnippetProvider.cs
+++ b/src/Features/CSharp/Portable/Snippets/CSharpIntMainSnippetProvider.cs
@@ -54,7 +54,7 @@ protected override async Task AddIndentationToDocumentAsync(Document d
var body = methodDeclaration.Body!;
var returnStatement = body.Statements.First();
- var syntaxFormattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false);
+ var syntaxFormattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var indentationString = CSharpSnippetHelpers.GetBlockLikeIndentationString(document, body.OpenBraceToken.SpanStart, syntaxFormattingOptions, cancellationToken);
var updatedReturnStatement = returnStatement.WithPrependedLeadingTrivia(SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, indentationString));
diff --git a/src/Features/CSharp/Portable/Snippets/CSharpSnippetHelpers.cs b/src/Features/CSharp/Portable/Snippets/CSharpSnippetHelpers.cs
index 40ee535b91968..9b6676458596c 100644
--- a/src/Features/CSharp/Portable/Snippets/CSharpSnippetHelpers.cs
+++ b/src/Features/CSharp/Portable/Snippets/CSharpSnippetHelpers.cs
@@ -49,7 +49,7 @@ public static async Task AddBlockIndentationToDocumentAsync
- BraceCompletionContext? GetCompletedBraceContext(ParsedDocument document, int caretLocation);
+ BraceCompletionContext? GetCompletedBraceContext(ParsedDocument document, StructuredAnalyzerConfigOptions fallbackOptions, int caretLocation);
///
/// Returns true if over typing should be allowed given the caret location and completed pair of braces.
@@ -89,10 +90,12 @@ internal readonly struct BraceCompletionResult(ImmutableArray textCh
public LinePosition CaretLocation { get; } = caretLocation;
}
-internal readonly struct BraceCompletionContext(ParsedDocument document, int openingPoint, int closingPoint, int caretLocation)
+internal readonly struct BraceCompletionContext(ParsedDocument document, StructuredAnalyzerConfigOptions fallbackOptions, int openingPoint, int closingPoint, int caretLocation)
{
public ParsedDocument Document { get; } = document;
+ public StructuredAnalyzerConfigOptions FallbackOptions { get; } = fallbackOptions;
+
public int OpeningPoint { get; } = openingPoint;
public int ClosingPoint { get; } = closingPoint;
diff --git a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs
index 928e676f85863..440ae7946921c 100644
--- a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs
+++ b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs
@@ -401,7 +401,7 @@ private static async Task> FindChangeSignatureR
});
var annotatedNodes = newRoot.GetAnnotatedNodes(syntaxAnnotation: changeSignatureFormattingAnnotation);
- var formattingOptions = await doc.GetSyntaxFormattingOptionsAsync(context.FallbackOptions, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = await doc.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
var formattedRoot = Formatter.Format(
newRoot,
diff --git a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs
index 42e5660f87dac..2ce7630a16636 100644
--- a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs
+++ b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs
@@ -53,10 +53,10 @@ public bool IsFixableDiagnostic(Diagnostic diagnostic)
public FixAllProvider? GetFixAllProvider()
=> null;
- public Task> GetFixesAsync(TextDocument document, TextSpan span, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ public Task> GetFixesAsync(TextDocument document, TextSpan span, IEnumerable diagnostics, CancellationToken cancellationToken)
=> Task.FromResult(GetConfigurations(document.Project, diagnostics));
- public Task> GetFixesAsync(Project project, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ public Task> GetFixesAsync(Project project, IEnumerable diagnostics, CancellationToken cancellationToken)
=> Task.FromResult(GetConfigurations(project, diagnostics));
private static ImmutableArray GetConfigurations(Project project, IEnumerable diagnostics)
diff --git a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureSeverity/ConfigureSeverityLevelCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureSeverity/ConfigureSeverityLevelCodeFixProvider.cs
index 5d8e0d9cc85ee..3ae7001b1ec2d 100644
--- a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureSeverity/ConfigureSeverityLevelCodeFixProvider.cs
+++ b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureSeverity/ConfigureSeverityLevelCodeFixProvider.cs
@@ -44,10 +44,10 @@ public bool IsFixableDiagnostic(Diagnostic diagnostic)
public FixAllProvider? GetFixAllProvider()
=> null;
- public Task> GetFixesAsync(TextDocument document, TextSpan span, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ public Task> GetFixesAsync(TextDocument document, TextSpan span, IEnumerable diagnostics, CancellationToken cancellationToken)
=> Task.FromResult(GetConfigurations(document.Project, diagnostics, cancellationToken));
- public Task> GetFixesAsync(Project project, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ public Task> GetFixesAsync(Project project, IEnumerable diagnostics, CancellationToken cancellationToken)
=> Task.FromResult(GetConfigurations(project, diagnostics, cancellationToken));
private static ImmutableArray GetConfigurations(Project project, IEnumerable diagnostics, CancellationToken cancellationToken)
diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageCodeAction.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageCodeAction.cs
index c9df6009c13d7..4c5dcd72e5d3f 100644
--- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageCodeAction.cs
+++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageCodeAction.cs
@@ -18,13 +18,11 @@ internal abstract partial class AbstractSuppressionCodeFixProvider : IConfigurat
internal sealed class GlobalSuppressMessageCodeAction(
ISymbol targetSymbol, INamedTypeSymbol suppressMessageAttribute,
Project project, Diagnostic diagnostic,
- AbstractSuppressionCodeFixProvider fixer,
- CodeActionOptionsProvider fallbackOptions) : AbstractGlobalSuppressMessageCodeAction(fixer, project)
+ AbstractSuppressionCodeFixProvider fixer) : AbstractGlobalSuppressMessageCodeAction(fixer, project)
{
private readonly ISymbol _targetSymbol = targetSymbol;
private readonly INamedTypeSymbol _suppressMessageAttribute = suppressMessageAttribute;
private readonly Diagnostic _diagnostic = diagnostic;
- private readonly CodeActionOptionsProvider _fallbackOptions = fallbackOptions;
protected override async Task GetChangedSuppressionDocumentAsync(CancellationToken cancellationToken)
{
@@ -32,7 +30,7 @@ protected override async Task GetChangedSuppressionDocumentAsync(Cance
var services = suppressionsDoc.Project.Solution.Services;
var suppressionsRoot = await suppressionsDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var addImportsService = suppressionsDoc.GetRequiredLanguageService();
- var options = await suppressionsDoc.GetSyntaxFormattingOptionsAsync(_fallbackOptions, cancellationToken).ConfigureAwait(false);
+ var options = await suppressionsDoc.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
suppressionsRoot = Fixer.AddGlobalSuppressMessageAttribute(
suppressionsRoot, _targetSymbol, _suppressMessageAttribute, _diagnostic, services, options, addImportsService, cancellationToken);
diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaBatchFixHelpers.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaBatchFixHelpers.cs
index 81bd3002bced4..dd7aab504f8e2 100644
--- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaBatchFixHelpers.cs
+++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaBatchFixHelpers.cs
@@ -34,7 +34,7 @@ public static CodeAction CreateBatchPragmaFix(
return CodeAction.Create(
((CodeAction)pragmaActions[0]).Title,
createChangedDocument: ct =>
- BatchPragmaFixesAsync(suppressionFixProvider, document, pragmaActions, pragmaDiagnostics, fixAllState.CodeActionOptionsProvider, cancellationToken),
+ BatchPragmaFixesAsync(suppressionFixProvider, document, pragmaActions, pragmaDiagnostics, cancellationToken),
equivalenceKey: fixAllState.CodeActionEquivalenceKey);
}
@@ -43,7 +43,6 @@ private static async Task BatchPragmaFixesAsync(
Document document,
ImmutableArray pragmaActions,
ImmutableArray diagnostics,
- CodeActionOptionsProvider fallbackOptions,
CancellationToken cancellationToken)
{
// We apply all the pragma suppression fixes sequentially.
@@ -86,7 +85,7 @@ private static async Task BatchPragmaFixesAsync(
properties: diagnostic.Properties,
isSuppressed: diagnostic.IsSuppressed);
- var newSuppressionFixes = await suppressionFixProvider.GetFixesAsync(currentDocument, currentDiagnosticSpan, [diagnostic], fallbackOptions, cancellationToken).ConfigureAwait(false);
+ var newSuppressionFixes = await suppressionFixProvider.GetFixesAsync(currentDocument, currentDiagnosticSpan, [diagnostic], cancellationToken).ConfigureAwait(false);
var newSuppressionFix = newSuppressionFixes.SingleOrDefault();
if (newSuppressionFix != null)
{
diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaWarningBatchFixAllProvider.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaWarningBatchFixAllProvider.cs
index 78695f9c6e311..40be76361e23a 100644
--- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaWarningBatchFixAllProvider.cs
+++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.PragmaWarningBatchFixAllProvider.cs
@@ -35,7 +35,7 @@ protected override async Task AddDocumentFixesAsync(
{
var span = diagnostic.Location.SourceSpan;
var pragmaSuppressions = await _suppressionFixProvider.GetPragmaSuppressionsAsync(
- document, span, [diagnostic], fixAllState.CodeActionOptionsProvider, cancellationToken).ConfigureAwait(false);
+ document, span, [diagnostic], cancellationToken).ConfigureAwait(false);
var pragmaSuppression = pragmaSuppressions.SingleOrDefault();
if (pragmaSuppression != null)
{
diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.BatchFixer.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.BatchFixer.cs
index 84ee578089529..ec1584616a016 100644
--- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.BatchFixer.cs
+++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.BatchFixer.cs
@@ -44,7 +44,7 @@ protected override async Task AddDocumentFixesAsync(
{
var span = diagnostic.Location.SourceSpan;
var removeSuppressionFixes = await _suppressionFixProvider.GetFixesAsync(
- document, span, [diagnostic], fixAllState.CodeActionOptionsProvider, cancellationToken).ConfigureAwait(false);
+ document, span, [diagnostic], cancellationToken).ConfigureAwait(false);
var removeSuppressionFix = removeSuppressionFixes.SingleOrDefault();
if (removeSuppressionFix != null)
{
@@ -89,7 +89,7 @@ protected override async Task AddProjectFixesAsync(
foreach (var diagnostic in diagnostics.Where(d => !d.Location.IsInSource && d.IsSuppressed))
{
var removeSuppressionFixes = await _suppressionFixProvider.GetFixesAsync(
- project, [diagnostic], fixAllState.CodeActionOptionsProvider, cancellationToken).ConfigureAwait(false);
+ project, [diagnostic], cancellationToken).ConfigureAwait(false);
if (removeSuppressionFixes.SingleOrDefault()?.Action is RemoveSuppressionCodeAction removeSuppressionCodeAction)
{
if (fixAllState.IsFixMultiple)
diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.cs
index 029be4d52cdea..b90e142d69b3b 100644
--- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.cs
+++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.RemoveSuppressionCodeAction.cs
@@ -27,7 +27,6 @@ public static async Task CreateAsync(
Project project,
Diagnostic diagnostic,
AbstractSuppressionCodeFixProvider fixer,
- CodeActionOptionsProvider options,
CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
@@ -38,7 +37,7 @@ public static async Task CreateAsync(
}
else if (documentOpt != null && !SuppressionHelpers.IsSynthesizedExternalSourceDiagnostic(diagnostic))
{
- var formattingOptions = await documentOpt.GetSyntaxFormattingOptionsAsync(options, cancellationToken).ConfigureAwait(false);
+ var formattingOptions = await documentOpt.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
return PragmaRemoveAction.Create(suppressionTargetInfo, documentOpt, formattingOptions, diagnostic, fixer);
}
else
diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.cs
index 410c85da807df..7afb14e30a060 100644
--- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.cs
+++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.cs
@@ -139,24 +139,24 @@ private SyntaxToken GetAdjustedTokenForPragmaRestore(SyntaxToken token, SyntaxNo
}
public Task> GetFixesAsync(
- TextDocument textDocument, TextSpan span, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ TextDocument textDocument, TextSpan span, IEnumerable diagnostics, CancellationToken cancellationToken)
{
if (textDocument is not Document document)
return Task.FromResult(ImmutableArray.Empty);
- return GetSuppressionsAsync(document, span, diagnostics, fallbackOptions, skipSuppressMessage: false, skipUnsuppress: false, cancellationToken: cancellationToken);
+ return GetSuppressionsAsync(document, span, diagnostics, skipSuppressMessage: false, skipUnsuppress: false, cancellationToken: cancellationToken);
}
- internal async Task> GetPragmaSuppressionsAsync(Document document, TextSpan span, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
+ internal async Task> GetPragmaSuppressionsAsync(Document document, TextSpan span, IEnumerable diagnostics, CancellationToken cancellationToken)
{
- var codeFixes = await GetSuppressionsAsync(document, span, diagnostics, fallbackOptions, skipSuppressMessage: true, skipUnsuppress: true, cancellationToken: cancellationToken).ConfigureAwait(false);
+ var codeFixes = await GetSuppressionsAsync(document, span, diagnostics, skipSuppressMessage: true, skipUnsuppress: true, cancellationToken: cancellationToken).ConfigureAwait(false);
return codeFixes.SelectMany(fix => fix.Action.NestedActions)
.OfType()
.ToImmutableArray();
}
private async Task> GetSuppressionsAsync(
- Document document, TextSpan span, IEnumerable diagnostics, CodeActionOptionsProvider fallbackOptions, bool skipSuppressMessage, bool skipUnsuppress, CancellationToken cancellationToken)
+ Document document, TextSpan span, IEnumerable diagnostics, bool skipSuppressMessage, bool skipUnsuppress, CancellationToken cancellationToken)
{
var suppressionTargetInfo = await GetSuppressionTargetInfoAsync(document, span, cancellationToken).ConfigureAwait(false);
if (suppressionTargetInfo == null)
@@ -165,11 +165,11 @@ private async Task