diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index ddb10ff6c6988..f853bdb36475d 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -207,7 +207,8 @@ and hence suppress this warning until we get closer to release and a more thorough documentation story --> - $(NoWarn);1573;1591;1701 + + $(NoWarn);1573;1591;1701;RS0016 $(DefineConstants);$(InitialDefineConstants) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 539c4c0801cd7..674b9140fd428 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6606,4 +6606,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Inheriting from a record with a sealed 'Object.ToString' is not supported in C# {0}. Please use language version '{1}' or greater. + + list pattern + + + slice pattern + + + length pattern + diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index a3bf13c2fb869..17d0394518890 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -4418,6 +4418,7 @@ private SymbolInfo GetNamedArgumentSymbolInfo(IdentifierNameSyntax identifierNam return (object)tupleElement == null ? SymbolInfo.None : new SymbolInfo(tupleElement, ImmutableArray.Empty, CandidateReason.None); } + // PROTOTYPE(list-patterns) SyntaxKind.ListPatternClause if (parent3.IsKind(SyntaxKind.PropertyPatternClause) || parent3.IsKind(SyntaxKind.PositionalPatternClause)) { return GetSymbolInfoWorker(identifierNameSyntax, SymbolInfoOptions.DefaultOptions, cancellationToken); diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index a999ea580e0de..be149388722dd 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -191,6 +191,11 @@ internal enum MessageID IDS_FeatureExternLocalFunctions = MessageBase + 12767, IDS_FeatureMemberNotNull = MessageBase + 12768, + // PROTOTYPE(list-patterns) To reduce conflicts with upstream. Should be moved eventually. + IDS_FeatureListPattern = MessageBase + 12800, + IDS_FeatureSlicePattern, + IDS_FeatureLengthPattern, + IDS_FeatureNativeInt = MessageBase + 12769, IDS_FeatureImplicitObjectCreation = MessageBase + 12770, IDS_FeatureTypePattern = MessageBase + 12771, @@ -491,6 +496,12 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) default: throw ExceptionUtilities.UnexpectedValue(feature); + + // PROTOTYPE(list-patterns) + case MessageID.IDS_FeatureListPattern: + case MessageID.IDS_FeatureSlicePattern: + case MessageID.IDS_FeatureLengthPattern: + return LanguageVersion.Preview; } } } diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 index e40f3eaedb827..dcf98ead9c9d9 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 +++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 @@ -550,6 +550,7 @@ pattern | parenthesized_pattern | recursive_pattern | relational_pattern + | slice_pattern | type_pattern | unary_pattern | var_pattern @@ -594,7 +595,7 @@ parenthesized_pattern ; recursive_pattern - : type? positional_pattern_clause? property_pattern_clause? variable_designation? + : type? positional_pattern_clause? length_pattern_clause? property_pattern_clause? variable_designation? ; positional_pattern_clause @@ -605,6 +606,10 @@ subpattern : name_colon? pattern ; +length_pattern_clause + : '[' pattern ']' + ; + property_pattern_clause : '{' (subpattern (',' subpattern)* ','?)? '}' ; @@ -618,6 +623,10 @@ relational_pattern | '>=' expression ; +slice_pattern + : '..' pattern? + ; + type_pattern : type ; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index 7a4108972ee84..393f4e5c9d45d 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs @@ -10460,13 +10460,14 @@ internal sealed partial class RecursivePatternSyntax : PatternSyntax { internal readonly TypeSyntax? type; internal readonly PositionalPatternClauseSyntax? positionalPatternClause; + internal readonly LengthPatternClauseSyntax? lengthPatternClause; internal readonly PropertyPatternClauseSyntax? propertyPatternClause; internal readonly VariableDesignationSyntax? designation; - internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) : base(kind, diagnostics, annotations) { - this.SlotCount = 4; + this.SlotCount = 5; if (type != null) { this.AdjustFlagsAndWidth(type); @@ -10477,6 +10478,11 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat this.AdjustFlagsAndWidth(positionalPatternClause); this.positionalPatternClause = positionalPatternClause; } + if (lengthPatternClause != null) + { + this.AdjustFlagsAndWidth(lengthPatternClause); + this.lengthPatternClause = lengthPatternClause; + } if (propertyPatternClause != null) { this.AdjustFlagsAndWidth(propertyPatternClause); @@ -10489,11 +10495,11 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat } } - internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation, SyntaxFactoryContext context) + internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation, SyntaxFactoryContext context) : base(kind) { this.SetFactoryContext(context); - this.SlotCount = 4; + this.SlotCount = 5; if (type != null) { this.AdjustFlagsAndWidth(type); @@ -10504,6 +10510,11 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat this.AdjustFlagsAndWidth(positionalPatternClause); this.positionalPatternClause = positionalPatternClause; } + if (lengthPatternClause != null) + { + this.AdjustFlagsAndWidth(lengthPatternClause); + this.lengthPatternClause = lengthPatternClause; + } if (propertyPatternClause != null) { this.AdjustFlagsAndWidth(propertyPatternClause); @@ -10516,10 +10527,10 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat } } - internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) : base(kind) { - this.SlotCount = 4; + this.SlotCount = 5; if (type != null) { this.AdjustFlagsAndWidth(type); @@ -10530,6 +10541,11 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat this.AdjustFlagsAndWidth(positionalPatternClause); this.positionalPatternClause = positionalPatternClause; } + if (lengthPatternClause != null) + { + this.AdjustFlagsAndWidth(lengthPatternClause); + this.lengthPatternClause = lengthPatternClause; + } if (propertyPatternClause != null) { this.AdjustFlagsAndWidth(propertyPatternClause); @@ -10544,6 +10560,7 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat public TypeSyntax? Type => this.type; public PositionalPatternClauseSyntax? PositionalPatternClause => this.positionalPatternClause; + public LengthPatternClauseSyntax? LengthPatternClause => this.lengthPatternClause; public PropertyPatternClauseSyntax? PropertyPatternClause => this.propertyPatternClause; public VariableDesignationSyntax? Designation => this.designation; @@ -10552,8 +10569,9 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat { 0 => this.type, 1 => this.positionalPatternClause, - 2 => this.propertyPatternClause, - 3 => this.designation, + 2 => this.lengthPatternClause, + 3 => this.propertyPatternClause, + 4 => this.designation, _ => null, }; @@ -10562,11 +10580,11 @@ internal RecursivePatternSyntax(SyntaxKind kind, TypeSyntax? type, PositionalPat public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitRecursivePattern(this); public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitRecursivePattern(this); - public RecursivePatternSyntax Update(TypeSyntax type, PositionalPatternClauseSyntax positionalPatternClause, PropertyPatternClauseSyntax propertyPatternClause, VariableDesignationSyntax designation) + public RecursivePatternSyntax Update(TypeSyntax type, PositionalPatternClauseSyntax positionalPatternClause, LengthPatternClauseSyntax lengthPatternClause, PropertyPatternClauseSyntax propertyPatternClause, VariableDesignationSyntax designation) { - if (type != this.Type || positionalPatternClause != this.PositionalPatternClause || propertyPatternClause != this.PropertyPatternClause || designation != this.Designation) + if (type != this.Type || positionalPatternClause != this.PositionalPatternClause || lengthPatternClause != this.LengthPatternClause || propertyPatternClause != this.PropertyPatternClause || designation != this.Designation) { - var newNode = SyntaxFactory.RecursivePattern(type, positionalPatternClause, propertyPatternClause, designation); + var newNode = SyntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause, propertyPatternClause, designation); var diags = GetDiagnostics(); if (diags?.Length > 0) newNode = newNode.WithDiagnosticsGreen(diags); @@ -10580,15 +10598,15 @@ public RecursivePatternSyntax Update(TypeSyntax type, PositionalPatternClauseSyn } internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) - => new RecursivePatternSyntax(this.Kind, this.type, this.positionalPatternClause, this.propertyPatternClause, this.designation, diagnostics, GetAnnotations()); + => new RecursivePatternSyntax(this.Kind, this.type, this.positionalPatternClause, this.lengthPatternClause, this.propertyPatternClause, this.designation, diagnostics, GetAnnotations()); internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) - => new RecursivePatternSyntax(this.Kind, this.type, this.positionalPatternClause, this.propertyPatternClause, this.designation, GetDiagnostics(), annotations); + => new RecursivePatternSyntax(this.Kind, this.type, this.positionalPatternClause, this.lengthPatternClause, this.propertyPatternClause, this.designation, GetDiagnostics(), annotations); internal RecursivePatternSyntax(ObjectReader reader) : base(reader) { - this.SlotCount = 4; + this.SlotCount = 5; var type = (TypeSyntax?)reader.ReadValue(); if (type != null) { @@ -10601,6 +10619,12 @@ internal RecursivePatternSyntax(ObjectReader reader) AdjustFlagsAndWidth(positionalPatternClause); this.positionalPatternClause = positionalPatternClause; } + var lengthPatternClause = (LengthPatternClauseSyntax?)reader.ReadValue(); + if (lengthPatternClause != null) + { + AdjustFlagsAndWidth(lengthPatternClause); + this.lengthPatternClause = lengthPatternClause; + } var propertyPatternClause = (PropertyPatternClauseSyntax?)reader.ReadValue(); if (propertyPatternClause != null) { @@ -10620,6 +10644,7 @@ internal override void WriteTo(ObjectWriter writer) base.WriteTo(writer); writer.WriteValue(this.type); writer.WriteValue(this.positionalPatternClause); + writer.WriteValue(this.lengthPatternClause); writer.WriteValue(this.propertyPatternClause); writer.WriteValue(this.designation); } @@ -10630,6 +10655,119 @@ static RecursivePatternSyntax() } } + internal sealed partial class LengthPatternClauseSyntax : CSharpSyntaxNode + { + internal readonly SyntaxToken openBracketToken; + internal readonly PatternSyntax pattern; + internal readonly SyntaxToken closeBracketToken; + + internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + : base(kind, diagnostics, annotations) + { + this.SlotCount = 3; + this.AdjustFlagsAndWidth(openBracketToken); + this.openBracketToken = openBracketToken; + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + this.AdjustFlagsAndWidth(closeBracketToken); + this.closeBracketToken = closeBracketToken; + } + + internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken, SyntaxFactoryContext context) + : base(kind) + { + this.SetFactoryContext(context); + this.SlotCount = 3; + this.AdjustFlagsAndWidth(openBracketToken); + this.openBracketToken = openBracketToken; + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + this.AdjustFlagsAndWidth(closeBracketToken); + this.closeBracketToken = closeBracketToken; + } + + internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) + : base(kind) + { + this.SlotCount = 3; + this.AdjustFlagsAndWidth(openBracketToken); + this.openBracketToken = openBracketToken; + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + this.AdjustFlagsAndWidth(closeBracketToken); + this.closeBracketToken = closeBracketToken; + } + + public SyntaxToken OpenBracketToken => this.openBracketToken; + public PatternSyntax Pattern => this.pattern; + public SyntaxToken CloseBracketToken => this.closeBracketToken; + + internal override GreenNode? GetSlot(int index) + => index switch + { + 0 => this.openBracketToken, + 1 => this.pattern, + 2 => this.closeBracketToken, + _ => null, + }; + + internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.LengthPatternClauseSyntax(this, parent, position); + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLengthPatternClause(this); + public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLengthPatternClause(this); + + public LengthPatternClauseSyntax Update(SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) + { + if (openBracketToken != this.OpenBracketToken || pattern != this.Pattern || closeBracketToken != this.CloseBracketToken) + { + var newNode = SyntaxFactory.LengthPatternClause(openBracketToken, pattern, closeBracketToken); + var diags = GetDiagnostics(); + if (diags?.Length > 0) + newNode = newNode.WithDiagnosticsGreen(diags); + var annotations = GetAnnotations(); + if (annotations?.Length > 0) + newNode = newNode.WithAnnotationsGreen(annotations); + return newNode; + } + + return this; + } + + internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) + => new LengthPatternClauseSyntax(this.Kind, this.openBracketToken, this.pattern, this.closeBracketToken, diagnostics, GetAnnotations()); + + internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) + => new LengthPatternClauseSyntax(this.Kind, this.openBracketToken, this.pattern, this.closeBracketToken, GetDiagnostics(), annotations); + + internal LengthPatternClauseSyntax(ObjectReader reader) + : base(reader) + { + this.SlotCount = 3; + var openBracketToken = (SyntaxToken)reader.ReadValue(); + AdjustFlagsAndWidth(openBracketToken); + this.openBracketToken = openBracketToken; + var pattern = (PatternSyntax)reader.ReadValue(); + AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + var closeBracketToken = (SyntaxToken)reader.ReadValue(); + AdjustFlagsAndWidth(closeBracketToken); + this.closeBracketToken = closeBracketToken; + } + + internal override void WriteTo(ObjectWriter writer) + { + base.WriteTo(writer); + writer.WriteValue(this.openBracketToken); + writer.WriteValue(this.pattern); + writer.WriteValue(this.closeBracketToken); + } + + static LengthPatternClauseSyntax() + { + ObjectBinder.RegisterTypeReader(typeof(LengthPatternClauseSyntax), r => new LengthPatternClauseSyntax(r)); + } + } + internal sealed partial class PositionalPatternClauseSyntax : CSharpSyntaxNode { internal readonly SyntaxToken openParenToken; @@ -10829,7 +10967,7 @@ public PropertyPatternClauseSyntax Update(SyntaxToken openBraceToken, Microsoft. { if (openBraceToken != this.OpenBraceToken || subpatterns != this.Subpatterns || closeBraceToken != this.CloseBraceToken) { - var newNode = SyntaxFactory.PropertyPatternClause(openBraceToken, subpatterns, closeBraceToken); + var newNode = SyntaxFactory.PropertyPatternClause(this.Kind, openBraceToken, subpatterns, closeBraceToken); var diags = GetDiagnostics(); if (diags?.Length > 0) newNode = newNode.WithDiagnosticsGreen(diags); @@ -11587,6 +11725,118 @@ static UnaryPatternSyntax() } } + internal sealed partial class SlicePatternSyntax : PatternSyntax + { + internal readonly SyntaxToken dotDotToken; + internal readonly PatternSyntax? pattern; + + internal SlicePatternSyntax(SyntaxKind kind, SyntaxToken dotDotToken, PatternSyntax? pattern, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + : base(kind, diagnostics, annotations) + { + this.SlotCount = 2; + this.AdjustFlagsAndWidth(dotDotToken); + this.dotDotToken = dotDotToken; + if (pattern != null) + { + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + } + } + + internal SlicePatternSyntax(SyntaxKind kind, SyntaxToken dotDotToken, PatternSyntax? pattern, SyntaxFactoryContext context) + : base(kind) + { + this.SetFactoryContext(context); + this.SlotCount = 2; + this.AdjustFlagsAndWidth(dotDotToken); + this.dotDotToken = dotDotToken; + if (pattern != null) + { + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + } + } + + internal SlicePatternSyntax(SyntaxKind kind, SyntaxToken dotDotToken, PatternSyntax? pattern) + : base(kind) + { + this.SlotCount = 2; + this.AdjustFlagsAndWidth(dotDotToken); + this.dotDotToken = dotDotToken; + if (pattern != null) + { + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + } + } + + public SyntaxToken DotDotToken => this.dotDotToken; + public PatternSyntax? Pattern => this.pattern; + + internal override GreenNode? GetSlot(int index) + => index switch + { + 0 => this.dotDotToken, + 1 => this.pattern, + _ => null, + }; + + internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.SlicePatternSyntax(this, parent, position); + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSlicePattern(this); + public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSlicePattern(this); + + public SlicePatternSyntax Update(SyntaxToken dotDotToken, PatternSyntax pattern) + { + if (dotDotToken != this.DotDotToken || pattern != this.Pattern) + { + var newNode = SyntaxFactory.SlicePattern(dotDotToken, pattern); + var diags = GetDiagnostics(); + if (diags?.Length > 0) + newNode = newNode.WithDiagnosticsGreen(diags); + var annotations = GetAnnotations(); + if (annotations?.Length > 0) + newNode = newNode.WithAnnotationsGreen(annotations); + return newNode; + } + + return this; + } + + internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) + => new SlicePatternSyntax(this.Kind, this.dotDotToken, this.pattern, diagnostics, GetAnnotations()); + + internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) + => new SlicePatternSyntax(this.Kind, this.dotDotToken, this.pattern, GetDiagnostics(), annotations); + + internal SlicePatternSyntax(ObjectReader reader) + : base(reader) + { + this.SlotCount = 2; + var dotDotToken = (SyntaxToken)reader.ReadValue(); + AdjustFlagsAndWidth(dotDotToken); + this.dotDotToken = dotDotToken; + var pattern = (PatternSyntax?)reader.ReadValue(); + if (pattern != null) + { + AdjustFlagsAndWidth(pattern); + this.pattern = pattern; + } + } + + internal override void WriteTo(ObjectWriter writer) + { + base.WriteTo(writer); + writer.WriteValue(this.dotDotToken); + writer.WriteValue(this.pattern); + } + + static SlicePatternSyntax() + { + ObjectBinder.RegisterTypeReader(typeof(SlicePatternSyntax), r => new SlicePatternSyntax(r)); + } + } + internal abstract partial class InterpolatedStringContentSyntax : CSharpSyntaxNode { internal InterpolatedStringContentSyntax(SyntaxKind kind, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) @@ -33042,6 +33292,7 @@ internal partial class CSharpSyntaxVisitor public virtual TResult VisitDeclarationPattern(DeclarationPatternSyntax node) => this.DefaultVisit(node); public virtual TResult VisitVarPattern(VarPatternSyntax node) => this.DefaultVisit(node); public virtual TResult VisitRecursivePattern(RecursivePatternSyntax node) => this.DefaultVisit(node); + public virtual TResult VisitLengthPatternClause(LengthPatternClauseSyntax node) => this.DefaultVisit(node); public virtual TResult VisitPositionalPatternClause(PositionalPatternClauseSyntax node) => this.DefaultVisit(node); public virtual TResult VisitPropertyPatternClause(PropertyPatternClauseSyntax node) => this.DefaultVisit(node); public virtual TResult VisitSubpattern(SubpatternSyntax node) => this.DefaultVisit(node); @@ -33051,6 +33302,7 @@ internal partial class CSharpSyntaxVisitor public virtual TResult VisitTypePattern(TypePatternSyntax node) => this.DefaultVisit(node); public virtual TResult VisitBinaryPattern(BinaryPatternSyntax node) => this.DefaultVisit(node); public virtual TResult VisitUnaryPattern(UnaryPatternSyntax node) => this.DefaultVisit(node); + public virtual TResult VisitSlicePattern(SlicePatternSyntax node) => this.DefaultVisit(node); public virtual TResult VisitInterpolatedStringText(InterpolatedStringTextSyntax node) => this.DefaultVisit(node); public virtual TResult VisitInterpolation(InterpolationSyntax node) => this.DefaultVisit(node); public virtual TResult VisitInterpolationAlignmentClause(InterpolationAlignmentClauseSyntax node) => this.DefaultVisit(node); @@ -33277,6 +33529,7 @@ internal partial class CSharpSyntaxVisitor public virtual void VisitDeclarationPattern(DeclarationPatternSyntax node) => this.DefaultVisit(node); public virtual void VisitVarPattern(VarPatternSyntax node) => this.DefaultVisit(node); public virtual void VisitRecursivePattern(RecursivePatternSyntax node) => this.DefaultVisit(node); + public virtual void VisitLengthPatternClause(LengthPatternClauseSyntax node) => this.DefaultVisit(node); public virtual void VisitPositionalPatternClause(PositionalPatternClauseSyntax node) => this.DefaultVisit(node); public virtual void VisitPropertyPatternClause(PropertyPatternClauseSyntax node) => this.DefaultVisit(node); public virtual void VisitSubpattern(SubpatternSyntax node) => this.DefaultVisit(node); @@ -33286,6 +33539,7 @@ internal partial class CSharpSyntaxVisitor public virtual void VisitTypePattern(TypePatternSyntax node) => this.DefaultVisit(node); public virtual void VisitBinaryPattern(BinaryPatternSyntax node) => this.DefaultVisit(node); public virtual void VisitUnaryPattern(UnaryPatternSyntax node) => this.DefaultVisit(node); + public virtual void VisitSlicePattern(SlicePatternSyntax node) => this.DefaultVisit(node); public virtual void VisitInterpolatedStringText(InterpolatedStringTextSyntax node) => this.DefaultVisit(node); public virtual void VisitInterpolation(InterpolationSyntax node) => this.DefaultVisit(node); public virtual void VisitInterpolationAlignmentClause(InterpolationAlignmentClauseSyntax node) => this.DefaultVisit(node); @@ -33682,7 +33936,10 @@ public override CSharpSyntaxNode VisitVarPattern(VarPatternSyntax node) => node.Update((SyntaxToken)Visit(node.VarKeyword), (VariableDesignationSyntax)Visit(node.Designation)); public override CSharpSyntaxNode VisitRecursivePattern(RecursivePatternSyntax node) - => node.Update((TypeSyntax)Visit(node.Type), (PositionalPatternClauseSyntax)Visit(node.PositionalPatternClause), (PropertyPatternClauseSyntax)Visit(node.PropertyPatternClause), (VariableDesignationSyntax)Visit(node.Designation)); + => node.Update((TypeSyntax)Visit(node.Type), (PositionalPatternClauseSyntax)Visit(node.PositionalPatternClause), (LengthPatternClauseSyntax)Visit(node.LengthPatternClause), (PropertyPatternClauseSyntax)Visit(node.PropertyPatternClause), (VariableDesignationSyntax)Visit(node.Designation)); + + public override CSharpSyntaxNode VisitLengthPatternClause(LengthPatternClauseSyntax node) + => node.Update((SyntaxToken)Visit(node.OpenBracketToken), (PatternSyntax)Visit(node.Pattern), (SyntaxToken)Visit(node.CloseBracketToken)); public override CSharpSyntaxNode VisitPositionalPatternClause(PositionalPatternClauseSyntax node) => node.Update((SyntaxToken)Visit(node.OpenParenToken), VisitList(node.Subpatterns), (SyntaxToken)Visit(node.CloseParenToken)); @@ -33711,6 +33968,9 @@ public override CSharpSyntaxNode VisitBinaryPattern(BinaryPatternSyntax node) public override CSharpSyntaxNode VisitUnaryPattern(UnaryPatternSyntax node) => node.Update((SyntaxToken)Visit(node.OperatorToken), (PatternSyntax)Visit(node.Pattern)); + public override CSharpSyntaxNode VisitSlicePattern(SlicePatternSyntax node) + => node.Update((SyntaxToken)Visit(node.DotDotToken), (PatternSyntax)Visit(node.Pattern)); + public override CSharpSyntaxNode VisitInterpolatedStringText(InterpolatedStringTextSyntax node) => node.Update((SyntaxToken)Visit(node.TextToken)); @@ -36016,12 +36276,35 @@ public VarPatternSyntax VarPattern(SyntaxToken varKeyword, VariableDesignationSy return result; } - public RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + public RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) { #if DEBUG #endif - return new RecursivePatternSyntax(SyntaxKind.RecursivePattern, type, positionalPatternClause, propertyPatternClause, designation, this.context); + return new RecursivePatternSyntax(SyntaxKind.RecursivePattern, type, positionalPatternClause, lengthPatternClause, propertyPatternClause, designation, this.context); + } + + public LengthPatternClauseSyntax LengthPatternClause(SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) + { +#if DEBUG + if (openBracketToken == null) throw new ArgumentNullException(nameof(openBracketToken)); + if (openBracketToken.Kind != SyntaxKind.OpenBracketToken) throw new ArgumentException(nameof(openBracketToken)); + if (pattern == null) throw new ArgumentNullException(nameof(pattern)); + if (closeBracketToken == null) throw new ArgumentNullException(nameof(closeBracketToken)); + if (closeBracketToken.Kind != SyntaxKind.CloseBracketToken) throw new ArgumentException(nameof(closeBracketToken)); +#endif + + int hash; + var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.LengthPatternClause, openBracketToken, pattern, closeBracketToken, this.context, out hash); + if (cached != null) return (LengthPatternClauseSyntax)cached; + + var result = new LengthPatternClauseSyntax(SyntaxKind.LengthPatternClause, openBracketToken, pattern, closeBracketToken, this.context); + if (hash >= 0) + { + SyntaxNodeCache.AddNode(result, hash); + } + + return result; } public PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken openParenToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeParenToken) @@ -36046,8 +36329,14 @@ public PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken openPar return result; } - public PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + public PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) { + switch (kind) + { + case SyntaxKind.PropertyPatternClause: + case SyntaxKind.ListPatternClause: break; + default: throw new ArgumentException(nameof(kind)); + } #if DEBUG if (openBraceToken == null) throw new ArgumentNullException(nameof(openBraceToken)); if (openBraceToken.Kind != SyntaxKind.OpenBraceToken) throw new ArgumentException(nameof(openBraceToken)); @@ -36056,10 +36345,10 @@ public PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken openBraceTo #endif int hash; - var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken, this.context, out hash); + var cached = CSharpSyntaxNodeCache.TryGetNode((int)kind, openBraceToken, subpatterns.Node, closeBraceToken, this.context, out hash); if (cached != null) return (PropertyPatternClauseSyntax)cached; - var result = new PropertyPatternClauseSyntax(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken, this.context); + var result = new PropertyPatternClauseSyntax(kind, openBraceToken, subpatterns.Node, closeBraceToken, this.context); if (hash >= 0) { SyntaxNodeCache.AddNode(result, hash); @@ -36232,6 +36521,26 @@ public UnaryPatternSyntax UnaryPattern(SyntaxToken operatorToken, PatternSyntax return result; } + public SlicePatternSyntax SlicePattern(SyntaxToken dotDotToken, PatternSyntax? pattern) + { +#if DEBUG + if (dotDotToken == null) throw new ArgumentNullException(nameof(dotDotToken)); + if (dotDotToken.Kind != SyntaxKind.DotDotToken) throw new ArgumentException(nameof(dotDotToken)); +#endif + + int hash; + var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.SlicePattern, dotDotToken, pattern, this.context, out hash); + if (cached != null) return (SlicePatternSyntax)cached; + + var result = new SlicePatternSyntax(SyntaxKind.SlicePattern, dotDotToken, pattern, this.context); + if (hash >= 0) + { + SyntaxNodeCache.AddNode(result, hash); + } + + return result; + } + public InterpolatedStringTextSyntax InterpolatedStringText(SyntaxToken textToken) { #if DEBUG @@ -40885,12 +41194,35 @@ public static VarPatternSyntax VarPattern(SyntaxToken varKeyword, VariableDesign return result; } - public static RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + public static RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + { +#if DEBUG +#endif + + return new RecursivePatternSyntax(SyntaxKind.RecursivePattern, type, positionalPatternClause, lengthPatternClause, propertyPatternClause, designation); + } + + public static LengthPatternClauseSyntax LengthPatternClause(SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) { #if DEBUG + if (openBracketToken == null) throw new ArgumentNullException(nameof(openBracketToken)); + if (openBracketToken.Kind != SyntaxKind.OpenBracketToken) throw new ArgumentException(nameof(openBracketToken)); + if (pattern == null) throw new ArgumentNullException(nameof(pattern)); + if (closeBracketToken == null) throw new ArgumentNullException(nameof(closeBracketToken)); + if (closeBracketToken.Kind != SyntaxKind.CloseBracketToken) throw new ArgumentException(nameof(closeBracketToken)); #endif - return new RecursivePatternSyntax(SyntaxKind.RecursivePattern, type, positionalPatternClause, propertyPatternClause, designation); + int hash; + var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.LengthPatternClause, openBracketToken, pattern, closeBracketToken, out hash); + if (cached != null) return (LengthPatternClauseSyntax)cached; + + var result = new LengthPatternClauseSyntax(SyntaxKind.LengthPatternClause, openBracketToken, pattern, closeBracketToken); + if (hash >= 0) + { + SyntaxNodeCache.AddNode(result, hash); + } + + return result; } public static PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken openParenToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeParenToken) @@ -40915,8 +41247,14 @@ public static PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken return result; } - public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) { + switch (kind) + { + case SyntaxKind.PropertyPatternClause: + case SyntaxKind.ListPatternClause: break; + default: throw new ArgumentException(nameof(kind)); + } #if DEBUG if (openBraceToken == null) throw new ArgumentNullException(nameof(openBraceToken)); if (openBraceToken.Kind != SyntaxKind.OpenBraceToken) throw new ArgumentException(nameof(openBraceToken)); @@ -40925,10 +41263,10 @@ public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken open #endif int hash; - var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken, out hash); + var cached = SyntaxNodeCache.TryGetNode((int)kind, openBraceToken, subpatterns.Node, closeBraceToken, out hash); if (cached != null) return (PropertyPatternClauseSyntax)cached; - var result = new PropertyPatternClauseSyntax(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken); + var result = new PropertyPatternClauseSyntax(kind, openBraceToken, subpatterns.Node, closeBraceToken); if (hash >= 0) { SyntaxNodeCache.AddNode(result, hash); @@ -41101,6 +41439,26 @@ public static UnaryPatternSyntax UnaryPattern(SyntaxToken operatorToken, Pattern return result; } + public static SlicePatternSyntax SlicePattern(SyntaxToken dotDotToken, PatternSyntax? pattern) + { +#if DEBUG + if (dotDotToken == null) throw new ArgumentNullException(nameof(dotDotToken)); + if (dotDotToken.Kind != SyntaxKind.DotDotToken) throw new ArgumentException(nameof(dotDotToken)); +#endif + + int hash; + var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.SlicePattern, dotDotToken, pattern, out hash); + if (cached != null) return (SlicePatternSyntax)cached; + + var result = new SlicePatternSyntax(SyntaxKind.SlicePattern, dotDotToken, pattern); + if (hash >= 0) + { + SyntaxNodeCache.AddNode(result, hash); + } + + return result; + } + public static InterpolatedStringTextSyntax InterpolatedStringText(SyntaxToken textToken) { #if DEBUG @@ -43951,6 +44309,7 @@ internal static IEnumerable GetNodeTypes() typeof(DeclarationPatternSyntax), typeof(VarPatternSyntax), typeof(RecursivePatternSyntax), + typeof(LengthPatternClauseSyntax), typeof(PositionalPatternClauseSyntax), typeof(PropertyPatternClauseSyntax), typeof(SubpatternSyntax), @@ -43960,6 +44319,7 @@ internal static IEnumerable GetNodeTypes() typeof(TypePatternSyntax), typeof(BinaryPatternSyntax), typeof(UnaryPatternSyntax), + typeof(SlicePatternSyntax), typeof(InterpolatedStringTextSyntax), typeof(InterpolationSyntax), typeof(InterpolationAlignmentClauseSyntax), diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index 86a0e9c3dc084..09ecb8281e66a 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -273,6 +273,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a RecursivePatternSyntax node. public virtual TResult? VisitRecursivePattern(RecursivePatternSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a LengthPatternClauseSyntax node. + public virtual TResult? VisitLengthPatternClause(LengthPatternClauseSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a PositionalPatternClauseSyntax node. public virtual TResult? VisitPositionalPatternClause(PositionalPatternClauseSyntax node) => this.DefaultVisit(node); @@ -300,6 +303,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a UnaryPatternSyntax node. public virtual TResult? VisitUnaryPattern(UnaryPatternSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a SlicePatternSyntax node. + public virtual TResult? VisitSlicePattern(SlicePatternSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a InterpolatedStringTextSyntax node. public virtual TResult? VisitInterpolatedStringText(InterpolatedStringTextSyntax node) => this.DefaultVisit(node); @@ -969,6 +975,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a RecursivePatternSyntax node. public virtual void VisitRecursivePattern(RecursivePatternSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a LengthPatternClauseSyntax node. + public virtual void VisitLengthPatternClause(LengthPatternClauseSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a PositionalPatternClauseSyntax node. public virtual void VisitPositionalPatternClause(PositionalPatternClauseSyntax node) => this.DefaultVisit(node); @@ -996,6 +1005,9 @@ public partial class CSharpSyntaxVisitor /// Called when the visitor visits a UnaryPatternSyntax node. public virtual void VisitUnaryPattern(UnaryPatternSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a SlicePatternSyntax node. + public virtual void VisitSlicePattern(SlicePatternSyntax node) => this.DefaultVisit(node); + /// Called when the visitor visits a InterpolatedStringTextSyntax node. public virtual void VisitInterpolatedStringText(InterpolatedStringTextSyntax node) => this.DefaultVisit(node); @@ -1663,7 +1675,10 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor => node.Update(VisitToken(node.VarKeyword), (VariableDesignationSyntax?)Visit(node.Designation) ?? throw new ArgumentNullException("designation")); public override SyntaxNode? VisitRecursivePattern(RecursivePatternSyntax node) - => node.Update((TypeSyntax?)Visit(node.Type), (PositionalPatternClauseSyntax?)Visit(node.PositionalPatternClause), (PropertyPatternClauseSyntax?)Visit(node.PropertyPatternClause), (VariableDesignationSyntax?)Visit(node.Designation)); + => node.Update((TypeSyntax?)Visit(node.Type), (PositionalPatternClauseSyntax?)Visit(node.PositionalPatternClause), (LengthPatternClauseSyntax?)Visit(node.LengthPatternClause), (PropertyPatternClauseSyntax?)Visit(node.PropertyPatternClause), (VariableDesignationSyntax?)Visit(node.Designation)); + + public override SyntaxNode? VisitLengthPatternClause(LengthPatternClauseSyntax node) + => node.Update(VisitToken(node.OpenBracketToken), (PatternSyntax?)Visit(node.Pattern) ?? throw new ArgumentNullException("pattern"), VisitToken(node.CloseBracketToken)); public override SyntaxNode? VisitPositionalPatternClause(PositionalPatternClauseSyntax node) => node.Update(VisitToken(node.OpenParenToken), VisitList(node.Subpatterns), VisitToken(node.CloseParenToken)); @@ -1692,6 +1707,9 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor public override SyntaxNode? VisitUnaryPattern(UnaryPatternSyntax node) => node.Update(VisitToken(node.OperatorToken), (PatternSyntax?)Visit(node.Pattern) ?? throw new ArgumentNullException("pattern")); + public override SyntaxNode? VisitSlicePattern(SlicePatternSyntax node) + => node.Update(VisitToken(node.DotDotToken), (PatternSyntax?)Visit(node.Pattern)); + public override SyntaxNode? VisitInterpolatedStringText(InterpolatedStringTextSyntax node) => node.Update(VisitToken(node.TextToken)); @@ -3552,14 +3570,27 @@ public static VarPatternSyntax VarPattern(VariableDesignationSyntax designation) => SyntaxFactory.VarPattern(SyntaxFactory.Token(SyntaxKind.VarKeyword), designation); /// Creates a new RecursivePatternSyntax instance. - public static RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + public static RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) { - return (RecursivePatternSyntax)Syntax.InternalSyntax.SyntaxFactory.RecursivePattern(type == null ? null : (Syntax.InternalSyntax.TypeSyntax)type.Green, positionalPatternClause == null ? null : (Syntax.InternalSyntax.PositionalPatternClauseSyntax)positionalPatternClause.Green, propertyPatternClause == null ? null : (Syntax.InternalSyntax.PropertyPatternClauseSyntax)propertyPatternClause.Green, designation == null ? null : (Syntax.InternalSyntax.VariableDesignationSyntax)designation.Green).CreateRed(); + return (RecursivePatternSyntax)Syntax.InternalSyntax.SyntaxFactory.RecursivePattern(type == null ? null : (Syntax.InternalSyntax.TypeSyntax)type.Green, positionalPatternClause == null ? null : (Syntax.InternalSyntax.PositionalPatternClauseSyntax)positionalPatternClause.Green, lengthPatternClause == null ? null : (Syntax.InternalSyntax.LengthPatternClauseSyntax)lengthPatternClause.Green, propertyPatternClause == null ? null : (Syntax.InternalSyntax.PropertyPatternClauseSyntax)propertyPatternClause.Green, designation == null ? null : (Syntax.InternalSyntax.VariableDesignationSyntax)designation.Green).CreateRed(); } /// Creates a new RecursivePatternSyntax instance. public static RecursivePatternSyntax RecursivePattern() - => SyntaxFactory.RecursivePattern(default, default, default, default); + => SyntaxFactory.RecursivePattern(default, default, default, default, default); + + /// Creates a new LengthPatternClauseSyntax instance. + public static LengthPatternClauseSyntax LengthPatternClause(SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) + { + if (openBracketToken.Kind() != SyntaxKind.OpenBracketToken) throw new ArgumentException(nameof(openBracketToken)); + if (pattern == null) throw new ArgumentNullException(nameof(pattern)); + if (closeBracketToken.Kind() != SyntaxKind.CloseBracketToken) throw new ArgumentException(nameof(closeBracketToken)); + return (LengthPatternClauseSyntax)Syntax.InternalSyntax.SyntaxFactory.LengthPatternClause((Syntax.InternalSyntax.SyntaxToken)openBracketToken.Node!, (Syntax.InternalSyntax.PatternSyntax)pattern.Green, (Syntax.InternalSyntax.SyntaxToken)closeBracketToken.Node!).CreateRed(); + } + + /// Creates a new LengthPatternClauseSyntax instance. + public static LengthPatternClauseSyntax LengthPatternClause(PatternSyntax pattern) + => SyntaxFactory.LengthPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), pattern, SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); /// Creates a new PositionalPatternClauseSyntax instance. public static PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken openParenToken, SeparatedSyntaxList subpatterns, SyntaxToken closeParenToken) @@ -3574,16 +3605,22 @@ public static PositionalPatternClauseSyntax PositionalPatternClause(SeparatedSyn => SyntaxFactory.PositionalPatternClause(SyntaxFactory.Token(SyntaxKind.OpenParenToken), subpatterns, SyntaxFactory.Token(SyntaxKind.CloseParenToken)); /// Creates a new PropertyPatternClauseSyntax instance. - public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken openBraceToken, SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SyntaxToken openBraceToken, SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) { + switch (kind) + { + case SyntaxKind.PropertyPatternClause: + case SyntaxKind.ListPatternClause: break; + default: throw new ArgumentException(nameof(kind)); + } if (openBraceToken.Kind() != SyntaxKind.OpenBraceToken) throw new ArgumentException(nameof(openBraceToken)); if (closeBraceToken.Kind() != SyntaxKind.CloseBraceToken) throw new ArgumentException(nameof(closeBraceToken)); - return (PropertyPatternClauseSyntax)Syntax.InternalSyntax.SyntaxFactory.PropertyPatternClause((Syntax.InternalSyntax.SyntaxToken)openBraceToken.Node!, subpatterns.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)closeBraceToken.Node!).CreateRed(); + return (PropertyPatternClauseSyntax)Syntax.InternalSyntax.SyntaxFactory.PropertyPatternClause(kind, (Syntax.InternalSyntax.SyntaxToken)openBraceToken.Node!, subpatterns.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)closeBraceToken.Node!).CreateRed(); } /// Creates a new PropertyPatternClauseSyntax instance. - public static PropertyPatternClauseSyntax PropertyPatternClause(SeparatedSyntaxList subpatterns = default) - => SyntaxFactory.PropertyPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBraceToken), subpatterns, SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SeparatedSyntaxList subpatterns = default) + => SyntaxFactory.PropertyPatternClause(kind, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), subpatterns, SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); /// Creates a new SubpatternSyntax instance. public static SubpatternSyntax Subpattern(NameColonSyntax? nameColon, PatternSyntax pattern) @@ -3684,6 +3721,17 @@ public static UnaryPatternSyntax UnaryPattern(SyntaxToken operatorToken, Pattern public static UnaryPatternSyntax UnaryPattern(PatternSyntax pattern) => SyntaxFactory.UnaryPattern(SyntaxFactory.Token(SyntaxKind.NotKeyword), pattern); + /// Creates a new SlicePatternSyntax instance. + public static SlicePatternSyntax SlicePattern(SyntaxToken dotDotToken, PatternSyntax? pattern) + { + if (dotDotToken.Kind() != SyntaxKind.DotDotToken) throw new ArgumentException(nameof(dotDotToken)); + return (SlicePatternSyntax)Syntax.InternalSyntax.SyntaxFactory.SlicePattern((Syntax.InternalSyntax.SyntaxToken)dotDotToken.Node!, pattern == null ? null : (Syntax.InternalSyntax.PatternSyntax)pattern.Green).CreateRed(); + } + + /// Creates a new SlicePatternSyntax instance. + public static SlicePatternSyntax SlicePattern(PatternSyntax? pattern = default) + => SyntaxFactory.SlicePattern(SyntaxFactory.Token(SyntaxKind.DotDotToken), pattern); + /// Creates a new InterpolatedStringTextSyntax instance. public static InterpolatedStringTextSyntax InterpolatedStringText(SyntaxToken textToken) { diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index 04aa76e5e9761..d430eb93dd10c 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -5015,6 +5015,7 @@ public sealed partial class RecursivePatternSyntax : PatternSyntax { private TypeSyntax? type; private PositionalPatternClauseSyntax? positionalPatternClause; + private LengthPatternClauseSyntax? lengthPatternClause; private PropertyPatternClauseSyntax? propertyPatternClause; private VariableDesignationSyntax? designation; @@ -5027,17 +5028,20 @@ internal RecursivePatternSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNod public PositionalPatternClauseSyntax? PositionalPatternClause => GetRed(ref this.positionalPatternClause, 1); - public PropertyPatternClauseSyntax? PropertyPatternClause => GetRed(ref this.propertyPatternClause, 2); + public LengthPatternClauseSyntax? LengthPatternClause => GetRed(ref this.lengthPatternClause, 2); - public VariableDesignationSyntax? Designation => GetRed(ref this.designation, 3); + public PropertyPatternClauseSyntax? PropertyPatternClause => GetRed(ref this.propertyPatternClause, 3); + + public VariableDesignationSyntax? Designation => GetRed(ref this.designation, 4); internal override SyntaxNode? GetNodeSlot(int index) => index switch { 0 => GetRedAtZero(ref this.type), 1 => GetRed(ref this.positionalPatternClause, 1), - 2 => GetRed(ref this.propertyPatternClause, 2), - 3 => GetRed(ref this.designation, 3), + 2 => GetRed(ref this.lengthPatternClause, 2), + 3 => GetRed(ref this.propertyPatternClause, 3), + 4 => GetRed(ref this.designation, 4), _ => null, }; @@ -5046,19 +5050,20 @@ internal RecursivePatternSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNod { 0 => this.type, 1 => this.positionalPatternClause, - 2 => this.propertyPatternClause, - 3 => this.designation, + 2 => this.lengthPatternClause, + 3 => this.propertyPatternClause, + 4 => this.designation, _ => null, }; public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitRecursivePattern(this); public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitRecursivePattern(this); - public RecursivePatternSyntax Update(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + public RecursivePatternSyntax Update(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, LengthPatternClauseSyntax? lengthPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) { - if (type != this.Type || positionalPatternClause != this.PositionalPatternClause || propertyPatternClause != this.PropertyPatternClause || designation != this.Designation) + if (type != this.Type || positionalPatternClause != this.PositionalPatternClause || lengthPatternClause != this.LengthPatternClause || propertyPatternClause != this.PropertyPatternClause || designation != this.Designation) { - var newNode = SyntaxFactory.RecursivePattern(type, positionalPatternClause, propertyPatternClause, designation); + var newNode = SyntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause, propertyPatternClause, designation); var annotations = GetAnnotations(); return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; } @@ -5066,21 +5071,62 @@ public RecursivePatternSyntax Update(TypeSyntax? type, PositionalPatternClauseSy return this; } - public RecursivePatternSyntax WithType(TypeSyntax? type) => Update(type, this.PositionalPatternClause, this.PropertyPatternClause, this.Designation); - public RecursivePatternSyntax WithPositionalPatternClause(PositionalPatternClauseSyntax? positionalPatternClause) => Update(this.Type, positionalPatternClause, this.PropertyPatternClause, this.Designation); - public RecursivePatternSyntax WithPropertyPatternClause(PropertyPatternClauseSyntax? propertyPatternClause) => Update(this.Type, this.PositionalPatternClause, propertyPatternClause, this.Designation); - public RecursivePatternSyntax WithDesignation(VariableDesignationSyntax? designation) => Update(this.Type, this.PositionalPatternClause, this.PropertyPatternClause, designation); + public RecursivePatternSyntax WithType(TypeSyntax? type) => Update(type, this.PositionalPatternClause, this.LengthPatternClause, this.PropertyPatternClause, this.Designation); + public RecursivePatternSyntax WithPositionalPatternClause(PositionalPatternClauseSyntax? positionalPatternClause) => Update(this.Type, positionalPatternClause, this.LengthPatternClause, this.PropertyPatternClause, this.Designation); + public RecursivePatternSyntax WithLengthPatternClause(LengthPatternClauseSyntax? lengthPatternClause) => Update(this.Type, this.PositionalPatternClause, lengthPatternClause, this.PropertyPatternClause, this.Designation); + public RecursivePatternSyntax WithPropertyPatternClause(PropertyPatternClauseSyntax? propertyPatternClause) => Update(this.Type, this.PositionalPatternClause, this.LengthPatternClause, propertyPatternClause, this.Designation); + public RecursivePatternSyntax WithDesignation(VariableDesignationSyntax? designation) => Update(this.Type, this.PositionalPatternClause, this.LengthPatternClause, this.PropertyPatternClause, designation); public RecursivePatternSyntax AddPositionalPatternClauseSubpatterns(params SubpatternSyntax[] items) { var positionalPatternClause = this.PositionalPatternClause ?? SyntaxFactory.PositionalPatternClause(); return WithPositionalPatternClause(positionalPatternClause.WithSubpatterns(positionalPatternClause.Subpatterns.AddRange(items))); } - public RecursivePatternSyntax AddPropertyPatternClauseSubpatterns(params SubpatternSyntax[] items) + } + + /// + /// This node is associated with the following syntax kinds: + /// + /// + /// + /// + public sealed partial class LengthPatternClauseSyntax : CSharpSyntaxNode + { + private PatternSyntax? pattern; + + internal LengthPatternClauseSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) + : base(green, parent, position) + { + } + + public SyntaxToken OpenBracketToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LengthPatternClauseSyntax)this.Green).openBracketToken, Position, 0); + + public PatternSyntax Pattern => GetRed(ref this.pattern, 1)!; + + public SyntaxToken CloseBracketToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LengthPatternClauseSyntax)this.Green).closeBracketToken, GetChildPosition(2), GetChildIndex(2)); + + internal override SyntaxNode? GetNodeSlot(int index) => index == 1 ? GetRed(ref this.pattern, 1)! : null; + + internal override SyntaxNode? GetCachedSlot(int index) => index == 1 ? this.pattern : null; + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitLengthPatternClause(this); + public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitLengthPatternClause(this); + + public LengthPatternClauseSyntax Update(SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) { - var propertyPatternClause = this.PropertyPatternClause ?? SyntaxFactory.PropertyPatternClause(); - return WithPropertyPatternClause(propertyPatternClause.WithSubpatterns(propertyPatternClause.Subpatterns.AddRange(items))); + if (openBracketToken != this.OpenBracketToken || pattern != this.Pattern || closeBracketToken != this.CloseBracketToken) + { + var newNode = SyntaxFactory.LengthPatternClause(openBracketToken, pattern, closeBracketToken); + var annotations = GetAnnotations(); + return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; + } + + return this; } + + public LengthPatternClauseSyntax WithOpenBracketToken(SyntaxToken openBracketToken) => Update(openBracketToken, this.Pattern, this.CloseBracketToken); + public LengthPatternClauseSyntax WithPattern(PatternSyntax pattern) => Update(this.OpenBracketToken, pattern, this.CloseBracketToken); + public LengthPatternClauseSyntax WithCloseBracketToken(SyntaxToken closeBracketToken) => Update(this.OpenBracketToken, this.Pattern, closeBracketToken); } /// @@ -5141,6 +5187,7 @@ public PositionalPatternClauseSyntax Update(SyntaxToken openParenToken, Separate /// This node is associated with the following syntax kinds: /// /// + /// /// /// public sealed partial class PropertyPatternClauseSyntax : CSharpSyntaxNode @@ -5176,7 +5223,7 @@ public PropertyPatternClauseSyntax Update(SyntaxToken openBraceToken, SeparatedS { if (openBraceToken != this.OpenBraceToken || subpatterns != this.Subpatterns || closeBraceToken != this.CloseBraceToken) { - var newNode = SyntaxFactory.PropertyPatternClause(openBraceToken, subpatterns, closeBraceToken); + var newNode = SyntaxFactory.PropertyPatternClause(this.Kind(), openBraceToken, subpatterns, closeBraceToken); var annotations = GetAnnotations(); return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; } @@ -5515,6 +5562,48 @@ public UnaryPatternSyntax Update(SyntaxToken operatorToken, PatternSyntax patter public UnaryPatternSyntax WithPattern(PatternSyntax pattern) => Update(this.OperatorToken, pattern); } + /// + /// This node is associated with the following syntax kinds: + /// + /// + /// + /// + public sealed partial class SlicePatternSyntax : PatternSyntax + { + private PatternSyntax? pattern; + + internal SlicePatternSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) + : base(green, parent, position) + { + } + + public SyntaxToken DotDotToken => new SyntaxToken(this, ((Syntax.InternalSyntax.SlicePatternSyntax)this.Green).dotDotToken, Position, 0); + + public PatternSyntax? Pattern => GetRed(ref this.pattern, 1); + + internal override SyntaxNode? GetNodeSlot(int index) => index == 1 ? GetRed(ref this.pattern, 1) : null; + + internal override SyntaxNode? GetCachedSlot(int index) => index == 1 ? this.pattern : null; + + public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitSlicePattern(this); + public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitSlicePattern(this); + + public SlicePatternSyntax Update(SyntaxToken dotDotToken, PatternSyntax? pattern) + { + if (dotDotToken != this.DotDotToken || pattern != this.Pattern) + { + var newNode = SyntaxFactory.SlicePattern(dotDotToken, pattern); + var annotations = GetAnnotations(); + return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; + } + + return this; + } + + public SlicePatternSyntax WithDotDotToken(SyntaxToken dotDotToken) => Update(dotDotToken, this.Pattern); + public SlicePatternSyntax WithPattern(PatternSyntax? pattern) => Update(this.DotDotToken, pattern); + } + public abstract partial class InterpolatedStringContentSyntax : CSharpSyntaxNode { internal InterpolatedStringContentSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position) diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs index 751f8d5a7383e..dca5a2db834c5 100644 --- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs +++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs @@ -10,6 +10,7 @@ // a specific target and scoped to a namespace, type, member, etc. [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.DeclarationPatternSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.ISymbol")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SlicePattern(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax)~Microsoft.CodeAnalysis.CSharp.Syntax.SlicePatternSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.TupleType(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.TupleTypeSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.TupleExpression(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WhenClause(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax)~Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax")] @@ -31,6 +32,7 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ArrayRankSpecifier(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.ArrayRankSpecifierSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.DeconstructionPattern(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.DeconstructionPatternSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyPatternClause(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternClauseSyntax")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PropertyPatternClause(Microsoft.CodeAnalysis.CSharp.SyntaxKind,Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.PropertyPatternClauseSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.PositionalPatternClause(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.PositionalPatternClauseSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.DeconstructionPatternClause(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.DeconstructionPatternClauseSyntax")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(System.String,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Text.Encoding,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.SyntaxTree")] diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 24b4d78971d71..44dfe4361c157 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6708,22 +6708,32 @@ bool canBeNullableType() case SyntaxKind.OpenBracketToken: // Now check for arrays. { - var ranks = _pool.Allocate(); - try + // We don't want to consume a sized rank specifier in patterns, we leave it out to parse it as a length pattern. + bool inPattern = (nameOptions & NameOptions.PossiblePattern) != 0; + if (!inPattern || isOmittedSize()) { - while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) + bool sawOpenBracket; + var ranks = _pool.Allocate(); + try { - var rank = this.ParseArrayRankSpecifier(out _); - ranks.Add(rank); + do + { + ranks.Add(this.ParseArrayRankSpecifier(out _)); + } + while ((sawOpenBracket = this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) && (!inPattern || isOmittedSize())); + + type = _syntaxFactory.ArrayType(type, ranks); + } + finally + { + _pool.Free(ranks); } - type = _syntaxFactory.ArrayType(type, ranks); - } - finally - { - _pool.Free(ranks); + // If we saw an open bracket that is not followed by an omitted size, it's possibly a length pattern. + if (!sawOpenBracket) + continue; } - continue; + goto done; // token not consumed } default: goto done; // token not consumed @@ -6733,6 +6743,8 @@ bool canBeNullableType() Debug.Assert(type != null); return type; + + bool isOmittedSize() => this.PeekToken(1).Kind is SyntaxKind.CommaToken or SyntaxKind.CloseBracketToken; } private SyntaxToken EatNullableQualifierIfApplicable(ParseTypeMode mode) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 2e6b9ecae1980..6f4ba91f68ac0 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -207,6 +207,10 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b switch (CurrentToken.Kind) { + case SyntaxKind.DotDotToken: + return _syntaxFactory.SlicePattern( + CheckFeatureAvailability(EatToken(), MessageID.IDS_FeatureSlicePattern), + IsPossibleSubpatternElement() ? ParseNegatedPattern(precedence, afterIs: false, whenIsKeyword) : null); case SyntaxKind.LessThanToken: case SyntaxKind.LessThanEqualsToken: case SyntaxKind.GreaterThanToken: @@ -301,8 +305,10 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden subPatterns: out SeparatedSyntaxList subPatterns, closeToken: out SyntaxToken closeParenToken, openKind: SyntaxKind.OpenParenToken, - closeKind: SyntaxKind.CloseParenToken); + closeKind: SyntaxKind.CloseParenToken, + isPropertyPatternClause: out _); + parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause0); parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0); parseDesignation(out VariableDesignationSyntax designation0); @@ -330,14 +336,15 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden } var positionalPatternClause = _syntaxFactory.PositionalPatternClause(openParenToken, subPatterns, closeParenToken); - var result = _syntaxFactory.RecursivePattern(type, positionalPatternClause, propertyPatternClause0, designation0); + var result = _syntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause0, propertyPatternClause0, designation0); return result; } - if (parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause)) + if (parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause) | + parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause)) { parseDesignation(out VariableDesignationSyntax designation0); - return _syntaxFactory.RecursivePattern(type, positionalPatternClause: null, propertyPatternClause, designation0); + return _syntaxFactory.RecursivePattern(type, positionalPatternClause: null, lengthPatternClause, propertyPatternClause, designation0); } if (type != null) @@ -363,6 +370,17 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden // let the caller fall back to parsing an expression return null; + bool parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause) + { + if (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) + { + lengthPatternClause = ParseLengthPatternClause(); + return true; + } + lengthPatternClause = null; + return false; + } + bool parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClauseResult) { propertyPatternClauseResult = null; @@ -397,6 +415,15 @@ bool looksLikeCast() } } + private LengthPatternClauseSyntax ParseLengthPatternClause() + { + var openBracket = EatToken(SyntaxKind.OpenBracketToken); + var pattern = ParsePattern(Precedence.Conditional); + var closeBracket = EatToken(SyntaxKind.CloseBracketToken); + var result = _syntaxFactory.LengthPatternClause(openBracket, pattern, closeBracket); + return CheckFeatureAvailability(result, MessageID.IDS_FeatureLengthPattern); + } + private bool IsValidPatternDesignation(bool whenIsKeyword) { if (CurrentToken.Kind == SyntaxKind.IdentifierToken) @@ -511,8 +538,10 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause() subPatterns: out SeparatedSyntaxList subPatterns, closeToken: out SyntaxToken closeBraceToken, openKind: SyntaxKind.OpenBraceToken, - closeKind: SyntaxKind.CloseBraceToken); - return _syntaxFactory.PropertyPatternClause(openBraceToken, subPatterns, closeBraceToken); + closeKind: SyntaxKind.CloseBraceToken, + out bool isPropertyPatternClause); + var kind = isPropertyPatternClause ? SyntaxKind.PropertyPatternClause : SyntaxKind.ListPatternClause; + return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken); } private void ParseSubpatternList( @@ -520,23 +549,26 @@ private void ParseSubpatternList( out SeparatedSyntaxList subPatterns, out SyntaxToken closeToken, SyntaxKind openKind, - SyntaxKind closeKind) + SyntaxKind closeKind, + out bool isPropertyPatternClause) { - Debug.Assert(openKind == SyntaxKind.OpenParenToken || openKind == SyntaxKind.OpenBraceToken); - Debug.Assert(closeKind == SyntaxKind.CloseParenToken || closeKind == SyntaxKind.CloseBraceToken); - Debug.Assert((openKind == SyntaxKind.OpenParenToken) == (closeKind == SyntaxKind.CloseParenToken)); + Debug.Assert((openKind, closeKind) is + (SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken) or + (SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)); Debug.Assert(openKind == this.CurrentToken.Kind); + isPropertyPatternClause = true; + openToken = this.EatToken(openKind); var list = _pool.AllocateSeparated(); try { tryAgain: - if (this.IsPossibleSubpatternElement() || this.CurrentToken.Kind == SyntaxKind.CommaToken) { + isPropertyPatternClause = false; // first pattern - list.Add(this.ParseSubpatternElement()); + list.Add(this.ParseSubpatternElement(ref isPropertyPatternClause)); // additional patterns int lastTokenPosition = -1; @@ -555,7 +587,7 @@ private void ParseSubpatternList( { break; } - list.Add(this.ParseSubpatternElement()); + list.Add(this.ParseSubpatternElement(ref isPropertyPatternClause)); continue; } else if (this.SkipBadPatternListTokens(ref openToken, list, SyntaxKind.CommaToken, closeKind) == PostSkipAction.Abort) @@ -578,7 +610,7 @@ private void ParseSubpatternList( } } - private SubpatternSyntax ParseSubpatternElement() + private SubpatternSyntax ParseSubpatternElement(ref bool sawNameColon) { NameColonSyntax nameColon = null; if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && this.PeekToken(1).Kind == SyntaxKind.ColonToken) @@ -586,6 +618,7 @@ private SubpatternSyntax ParseSubpatternElement() var name = this.ParseIdentifierName(); var colon = this.EatToken(SyntaxKind.ColonToken); nameColon = _syntaxFactory.NameColon(name, colon); + sawNameColon = true; } var pattern = ParsePattern(Precedence.Conditional); @@ -600,15 +633,13 @@ private SubpatternSyntax ParseSubpatternElement() private bool IsPossibleSubpatternElement() { return this.IsPossibleExpression(allowBinaryExpressions: false, allowAssignmentExpressions: false) || - this.CurrentToken.Kind switch - { - SyntaxKind.OpenBraceToken => true, - SyntaxKind.LessThanToken => true, - SyntaxKind.LessThanEqualsToken => true, - SyntaxKind.GreaterThanToken => true, - SyntaxKind.GreaterThanEqualsToken => true, - _ => false - }; + this.CurrentToken.Kind is + SyntaxKind.OpenBraceToken or + SyntaxKind.OpenBracketToken or + SyntaxKind.LessThanToken or + SyntaxKind.LessThanEqualsToken or + SyntaxKind.GreaterThanToken or + SyntaxKind.GreaterThanEqualsToken; } private PostSkipAction SkipBadPatternListTokens( diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 47fdde3be2e2f..78cdcc4bdbf1a 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1 +1,4 @@ override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetUsedAssemblyReferences(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.CSharp.SyntaxKind.SlicePattern = 9034 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.LengthPatternClause = 9035 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.ListPatternClause = 9036 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind diff --git a/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs new file mode 100644 index 0000000000000..4032b57704448 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.CodeAnalysis.CSharp +{ + public partial class SyntaxFactory + { + public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken openBraceToken, SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + { + return PropertyPatternClause(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns, closeBraceToken); + } + + public static PropertyPatternClauseSyntax PropertyPatternClause(SeparatedSyntaxList subpatterns = default) + { + return PropertyPatternClause(SyntaxKind.PropertyPatternClause, subpatterns); + } + } +} diff --git a/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs new file mode 100644 index 0000000000000..0138199debf84 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.CodeAnalysis.CSharp.Syntax +{ + public partial class RecursivePatternSyntax + { + public RecursivePatternSyntax Update(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + { + return Update(type, positionalPatternClause, this.LengthPatternClause, propertyPatternClause, designation); + } + + public RecursivePatternSyntax AddPropertyPatternClauseSubpatterns(params SubpatternSyntax[] items) + { + var propertyPatternClause = this.PropertyPatternClause ?? SyntaxFactory.PropertyPatternClause(); + return WithPropertyPatternClause(propertyPatternClause.WithSubpatterns(propertyPatternClause.Subpatterns.AddRange(items))); + } + } +} + +namespace Microsoft.CodeAnalysis.CSharp +{ + public partial class SyntaxFactory + { + public static RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) + { + return RecursivePattern(type, positionalPatternClause, lengthPatternClause: null, propertyPatternClause, designation); + } + } +} diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index f24059e17aa41..d2371ee50b256 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -2002,12 +2002,23 @@ + + + + + + + + + + + @@ -2020,6 +2031,7 @@ + @@ -2093,6 +2105,13 @@ + + + + + + + diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 4686c56198157..45829f23243cd 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -827,6 +827,11 @@ public enum SyntaxKind : ushort AndPattern = 9032, NotPattern = 9033, + // new patterns added in C# 10.0 + SlicePattern = 9034, + LengthPatternClause = 9035, + ListPatternClause = 9036, + // Kinds between 9000 and 9039 are "reserved" for pattern matching. DeclarationExpression = 9040, diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index ac1a9531bd044..cf2011ddfef2d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -977,11 +977,26 @@ Vytvoření objektu s cílovým typem + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Sestavení {0}, které obsahuje typ {1}, se odkazuje na architekturu .NET Framework, což se nepodporuje. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index c13857bef8189..e2c44555f5e45 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -977,11 +977,26 @@ Objekterstellung mit Zieltyp + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Die Assembly "{0}" mit dem Typ "{1}" verweist auf das .NET Framework. Dies wird nicht unterstützt. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index e77b6c0174b94..b4d0ae7065265 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -977,11 +977,26 @@ creación de objetos con tipo de destino + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. El ensamblado "{0}" que contiene el tipo "{1}" hace referencia a .NET Framework, lo cual no se admite. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 09aa035471de8..26b99702a1ddb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -977,11 +977,26 @@ création d'un objet typé cible + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. L'assembly '{0}' contenant le type '{1}' référence le .NET Framework, ce qui n'est pas pris en charge. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 23ba661cefe46..2b4829f127dac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -977,11 +977,26 @@ creazione di oggetti con tipo di destinazione + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. L'assembly '{0}' che contiene il tipo '{1}' fa riferimento a .NET Framework, che non è supportato. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index b514b4403a277..64d5cd824c1b9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -977,11 +977,26 @@ target-typed オブジェクトの作成 + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 型 '{1}' を含むアセンブリ '{0}' が .NET Framework を参照しています。これはサポートされていません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 4d1e5edcf9666..8263349ee8aa8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -977,11 +977,26 @@ 대상으로 형식화된 개체 만들기 + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. '{1}' 형식을 포함하는 '{0}' 어셈블리가 지원되지 않는 .NET Framework를 참조합니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 761e1ae2d9251..f2be468b5bdea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -977,11 +977,26 @@ tworzenie obiektu z typem docelowym + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Zestaw „{0}” zawierający typ „{1}” odwołuje się do platformy .NET Framework, co nie jest obsługiwane. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 349c28c45bc43..535b5f8beb48f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -977,11 +977,26 @@ criação de objeto de tipo de destino + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. O assembly '{0}' contendo o tipo '{1}' referencia o .NET Framework, mas não há suporte para isso. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 6bcc64b24402b..3a97067f81bda 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -977,11 +977,26 @@ создание объекта с типом целевого объекта + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Сборка "{0}", содержащая тип "{1}", ссылается на платформу .NET Framework, которая не поддерживается. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index fcbbf5ccca853..a47e819754a8f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -977,11 +977,26 @@ hedeflenen türde nesne oluşturma + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. '{1}' türünü içeren '{0}' bütünleştirilmiş kodu, desteklenmeyen .NET Framework'e başvuruyor. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 2b3e67c909fc6..349126cfbbc4c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -977,11 +977,26 @@ 创建目标类型对象 + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 包含类型“{1}”的程序集“{0}”引用了 .NET Framework,而此操作不受支持。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 2c811ba28ee0e..a12cb2fb7b694 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -977,11 +977,26 @@ 建立具目標類型的物件 + + length pattern + length pattern + + + + list pattern + list pattern + + sealed ToString in record sealed ToString in record + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 包含類型 '{1}' 的組件 '{0}' 參考了 .NET Framework,此情形不受支援。 diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs index 5ecd5a7f3e309..af592087663b3 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs @@ -1088,18 +1088,15 @@ void M1(object o, bool b) var compilation = CreateCompilation(source, new[] { vbCompilation.EmitToImageReference() }, parseOptions: TestOptions.Regular8); compilation.VerifyDiagnostics( - // (6,33): error CS8400: Feature 'type pattern' is not available in C# 8.0. Please use language version 9.0 or greater. - // b = /**/o is C1 { Prop[1]: var x }/**/; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "Prop[1]").WithArguments("type pattern", "9.0").WithLocation(6, 33), // (6,33): error CS8503: A property subpattern requires a reference to the property or field to be matched, e.g. '{ Name: Prop[1] }' // b = /**/o is C1 { Prop[1]: var x }/**/; Diagnostic(ErrorCode.ERR_PropertyPatternNameMissing, "Prop[1]").WithArguments("Prop[1]").WithLocation(6, 33), // (6,33): error CS0246: The type or namespace name 'Prop' could not be found (are you missing a using directive or an assembly reference?) // b = /**/o is C1 { Prop[1]: var x }/**/; Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Prop").WithArguments("Prop").WithLocation(6, 33), - // (6,37): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression) + // (6,37): error CS8652: The feature 'length pattern' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // b = /**/o is C1 { Prop[1]: var x }/**/; - Diagnostic(ErrorCode.ERR_ArraySizeInDeclaration, "[1]").WithLocation(6, 37), + Diagnostic(ErrorCode.ERR_FeatureInPreview, "[1]").WithArguments("length pattern").WithLocation(6, 37), // (6,40): error CS1003: Syntax error, ',' expected // b = /**/o is C1 { Prop[1]: var x }/**/; Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments(",", ":").WithLocation(6, 40), @@ -1120,7 +1117,9 @@ void M1(object o, bool b) IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'Prop[1]') Children(0) Pattern: - ITypePatternOperation (OperationKind.TypePattern, Type: null, IsInvalid) (Syntax: 'Prop[1]') (InputType: ?, NarrowedType: Prop[], MatchedType: Prop[]) + IRecursivePatternOperation (OperationKind.RecursivePattern, Type: null, IsInvalid) (Syntax: 'Prop[1]') (InputType: ?, NarrowedType: Prop, DeclaredSymbol: null, MatchedType: Prop, DeconstructSymbol: null) + DeconstructionSubpatterns (0) + PropertySubpatterns (0) IPropertySubpatternOperation (OperationKind.PropertySubpattern, Type: null, IsInvalid) (Syntax: 'var x') Member: IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'var x') diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs index edeb611cea0f9..94dd2ad7f717b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs +++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs @@ -33,6 +33,10 @@ public void DiagnosticAnalyzerAllInOne() // https://github.com/dotnet/roslyn/issues/44682 Add to all in one missingSyntaxKinds.Add(SyntaxKind.WithExpression); missingSyntaxKinds.Add(SyntaxKind.RecordDeclaration); + // PROTOTYPE(list-patterns) + missingSyntaxKinds.Add(SyntaxKind.SlicePattern); + missingSyntaxKinds.Add(SyntaxKind.LengthPatternClause); + missingSyntaxKinds.Add(SyntaxKind.ListPatternClause); var analyzer = new CSharpTrackingDiagnosticAnalyzer(); var options = new AnalyzerOptions(new[] { new TestAdditionalText() }.ToImmutableArray()); diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index fe56c3ae30b27..4be42307aa1df 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -266,13 +266,16 @@ private static Syntax.InternalSyntax.VarPatternSyntax GenerateVarPattern() => InternalSyntaxFactory.VarPattern(InternalSyntaxFactory.Token(SyntaxKind.VarKeyword), GenerateSingleVariableDesignation()); private static Syntax.InternalSyntax.RecursivePatternSyntax GenerateRecursivePattern() - => InternalSyntaxFactory.RecursivePattern(null, null, null, null); + => InternalSyntaxFactory.RecursivePattern(null, null, null, null, null); + + private static Syntax.InternalSyntax.LengthPatternClauseSyntax GenerateLengthPatternClause() + => InternalSyntaxFactory.LengthPatternClause(InternalSyntaxFactory.Token(SyntaxKind.OpenBracketToken), GenerateDiscardPattern(), InternalSyntaxFactory.Token(SyntaxKind.CloseBracketToken)); private static Syntax.InternalSyntax.PositionalPatternClauseSyntax GeneratePositionalPatternClause() => InternalSyntaxFactory.PositionalPatternClause(InternalSyntaxFactory.Token(SyntaxKind.OpenParenToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseParenToken)); private static Syntax.InternalSyntax.PropertyPatternClauseSyntax GeneratePropertyPatternClause() - => InternalSyntaxFactory.PropertyPatternClause(InternalSyntaxFactory.Token(SyntaxKind.OpenBraceToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + => InternalSyntaxFactory.PropertyPatternClause(SyntaxKind.PropertyPatternClause, InternalSyntaxFactory.Token(SyntaxKind.OpenBraceToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseBraceToken)); private static Syntax.InternalSyntax.SubpatternSyntax GenerateSubpattern() => InternalSyntaxFactory.Subpattern(null, GenerateDiscardPattern()); @@ -295,6 +298,9 @@ private static Syntax.InternalSyntax.BinaryPatternSyntax GenerateBinaryPattern() private static Syntax.InternalSyntax.UnaryPatternSyntax GenerateUnaryPattern() => InternalSyntaxFactory.UnaryPattern(InternalSyntaxFactory.Token(SyntaxKind.NotKeyword), GenerateDiscardPattern()); + private static Syntax.InternalSyntax.SlicePatternSyntax GenerateSlicePattern() + => InternalSyntaxFactory.SlicePattern(InternalSyntaxFactory.Token(SyntaxKind.DotDotToken), null); + private static Syntax.InternalSyntax.InterpolatedStringTextSyntax GenerateInterpolatedStringText() => InternalSyntaxFactory.InterpolatedStringText(InternalSyntaxFactory.Token(SyntaxKind.InterpolatedStringTextToken)); @@ -1719,12 +1725,25 @@ public void TestRecursivePatternFactoryAndProperties() Assert.Null(node.Type); Assert.Null(node.PositionalPatternClause); + Assert.Null(node.LengthPatternClause); Assert.Null(node.PropertyPatternClause); Assert.Null(node.Designation); AttachAndCheckDiagnostics(node); } + [Fact] + public void TestLengthPatternClauseFactoryAndProperties() + { + var node = GenerateLengthPatternClause(); + + Assert.Equal(SyntaxKind.OpenBracketToken, node.OpenBracketToken.Kind); + Assert.NotNull(node.Pattern); + Assert.Equal(SyntaxKind.CloseBracketToken, node.CloseBracketToken.Kind); + + AttachAndCheckDiagnostics(node); + } + [Fact] public void TestPositionalPatternClauseFactoryAndProperties() { @@ -1826,6 +1845,17 @@ public void TestUnaryPatternFactoryAndProperties() AttachAndCheckDiagnostics(node); } + [Fact] + public void TestSlicePatternFactoryAndProperties() + { + var node = GenerateSlicePattern(); + + Assert.Equal(SyntaxKind.DotDotToken, node.DotDotToken.Kind); + Assert.Null(node.Pattern); + + AttachAndCheckDiagnostics(node); + } + [Fact] public void TestInterpolatedStringTextFactoryAndProperties() { @@ -5898,6 +5928,32 @@ public void TestRecursivePatternIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestLengthPatternClauseTokenDeleteRewriter() + { + var oldNode = GenerateLengthPatternClause(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestLengthPatternClauseIdentityRewriter() + { + var oldNode = GenerateLengthPatternClause(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestPositionalPatternClauseTokenDeleteRewriter() { @@ -6132,6 +6188,32 @@ public void TestUnaryPatternIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestSlicePatternTokenDeleteRewriter() + { + var oldNode = GenerateSlicePattern(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestSlicePatternIdentityRewriter() + { + var oldNode = GenerateSlicePattern(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestInterpolatedStringTextTokenDeleteRewriter() { @@ -9929,13 +10011,16 @@ private static VarPatternSyntax GenerateVarPattern() => SyntaxFactory.VarPattern(SyntaxFactory.Token(SyntaxKind.VarKeyword), GenerateSingleVariableDesignation()); private static RecursivePatternSyntax GenerateRecursivePattern() - => SyntaxFactory.RecursivePattern(default(TypeSyntax), default(PositionalPatternClauseSyntax), default(PropertyPatternClauseSyntax), default(VariableDesignationSyntax)); + => SyntaxFactory.RecursivePattern(default(TypeSyntax), default(PositionalPatternClauseSyntax), default(LengthPatternClauseSyntax), default(PropertyPatternClauseSyntax), default(VariableDesignationSyntax)); + + private static LengthPatternClauseSyntax GenerateLengthPatternClause() + => SyntaxFactory.LengthPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), GenerateDiscardPattern(), SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); private static PositionalPatternClauseSyntax GeneratePositionalPatternClause() => SyntaxFactory.PositionalPatternClause(SyntaxFactory.Token(SyntaxKind.OpenParenToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseParenToken)); private static PropertyPatternClauseSyntax GeneratePropertyPatternClause() - => SyntaxFactory.PropertyPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + => SyntaxFactory.PropertyPatternClause(SyntaxKind.PropertyPatternClause, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); private static SubpatternSyntax GenerateSubpattern() => SyntaxFactory.Subpattern(default(NameColonSyntax), GenerateDiscardPattern()); @@ -9958,6 +10043,9 @@ private static BinaryPatternSyntax GenerateBinaryPattern() private static UnaryPatternSyntax GenerateUnaryPattern() => SyntaxFactory.UnaryPattern(SyntaxFactory.Token(SyntaxKind.NotKeyword), GenerateDiscardPattern()); + private static SlicePatternSyntax GenerateSlicePattern() + => SyntaxFactory.SlicePattern(SyntaxFactory.Token(SyntaxKind.DotDotToken), default(PatternSyntax)); + private static InterpolatedStringTextSyntax GenerateInterpolatedStringText() => SyntaxFactory.InterpolatedStringText(SyntaxFactory.Token(SyntaxKind.InterpolatedStringTextToken)); @@ -11382,9 +11470,22 @@ public void TestRecursivePatternFactoryAndProperties() Assert.Null(node.Type); Assert.Null(node.PositionalPatternClause); + Assert.Null(node.LengthPatternClause); Assert.Null(node.PropertyPatternClause); Assert.Null(node.Designation); - var newNode = node.WithType(node.Type).WithPositionalPatternClause(node.PositionalPatternClause).WithPropertyPatternClause(node.PropertyPatternClause).WithDesignation(node.Designation); + var newNode = node.WithType(node.Type).WithPositionalPatternClause(node.PositionalPatternClause).WithLengthPatternClause(node.LengthPatternClause).WithPropertyPatternClause(node.PropertyPatternClause).WithDesignation(node.Designation); + Assert.Equal(node, newNode); + } + + [Fact] + public void TestLengthPatternClauseFactoryAndProperties() + { + var node = GenerateLengthPatternClause(); + + Assert.Equal(SyntaxKind.OpenBracketToken, node.OpenBracketToken.Kind()); + Assert.NotNull(node.Pattern); + Assert.Equal(SyntaxKind.CloseBracketToken, node.CloseBracketToken.Kind()); + var newNode = node.WithOpenBracketToken(node.OpenBracketToken).WithPattern(node.Pattern).WithCloseBracketToken(node.CloseBracketToken); Assert.Equal(node, newNode); } @@ -11489,6 +11590,17 @@ public void TestUnaryPatternFactoryAndProperties() Assert.Equal(node, newNode); } + [Fact] + public void TestSlicePatternFactoryAndProperties() + { + var node = GenerateSlicePattern(); + + Assert.Equal(SyntaxKind.DotDotToken, node.DotDotToken.Kind()); + Assert.Null(node.Pattern); + var newNode = node.WithDotDotToken(node.DotDotToken).WithPattern(node.Pattern); + Assert.Equal(node, newNode); + } + [Fact] public void TestInterpolatedStringTextFactoryAndProperties() { @@ -15561,6 +15673,32 @@ public void TestRecursivePatternIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestLengthPatternClauseTokenDeleteRewriter() + { + var oldNode = GenerateLengthPatternClause(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestLengthPatternClauseIdentityRewriter() + { + var oldNode = GenerateLengthPatternClause(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestPositionalPatternClauseTokenDeleteRewriter() { @@ -15795,6 +15933,32 @@ public void TestUnaryPatternIdentityRewriter() Assert.Same(oldNode, newNode); } + [Fact] + public void TestSlicePatternTokenDeleteRewriter() + { + var oldNode = GenerateSlicePattern(); + var rewriter = new TokenDeleteRewriter(); + var newNode = rewriter.Visit(oldNode); + + if(!oldNode.IsMissing) + { + Assert.NotEqual(oldNode, newNode); + } + + Assert.NotNull(newNode); + Assert.True(newNode.IsMissing, "No tokens => missing"); + } + + [Fact] + public void TestSlicePatternIdentityRewriter() + { + var oldNode = GenerateSlicePattern(); + var rewriter = new IdentityRewriter(); + var newNode = rewriter.Visit(oldNode); + + Assert.Same(oldNode, newNode); + } + [Fact] public void TestInterpolatedStringTextTokenDeleteRewriter() { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs index 6ab590092da35..fee8745b097f5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs @@ -6669,7 +6669,7 @@ public void TrailingCommaInPropertyPattern_02() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); M(SyntaxKind.Subpattern); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs new file mode 100644 index 0000000000000..024c9af699370 --- /dev/null +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -0,0 +1,1521 @@ +// Licensed to the .NET Foundation under one or more 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 Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class PatternParsingTests_ListPatterns : ParsingTests + { + private new void UsingExpression(string text, params DiagnosticDescription[] expectedErrors) + { + UsingExpression(text, options: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview), expectedErrors); + } + + public PatternParsingTests_ListPatterns(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void LengthPattern_01() + { + UsingExpression(@"c is [0]{}"); + verify(); + + UsingExpression(@"c is [0]{}", TestOptions.Regular9, + // (1,6): error CS8652: The feature 'length pattern' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // c is [0]{} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "[0]").WithArguments("length pattern").WithLocation(1, 6)); + verify(); + + void verify() + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + } + + [Fact] + public void LengthPattern_02() + { + UsingExpression(@"c is [>0]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.RelationalPattern); + { + N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_03() + { + UsingExpression(@"c is [_]{P:P}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.DiscardPattern); + { + N(SyntaxKind.UnderscoreToken); + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "P"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "P"); + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_04() + { + UsingExpression(@"c is ()[0]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PositionalPatternClause); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_05() + { + UsingExpression(@"c is int[][0]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + 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.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_06() + { + UsingExpression(@"c is int[0]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_07() + { + UsingExpression(@"c is List[0]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "List"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_08() + { + UsingExpression(@"c is [{}]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + } + + [Fact] + public void LengthPattern_09() + { + UsingExpression(@"c is C1 { Prop[1]: var x }", + // (1,18): error CS1003: Syntax error, ',' expected + // c is C1 { Prop[1]: var x } + Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments(",", ":").WithLocation(1, 18), + // (1,20): error CS1003: Syntax error, ',' expected + // c is C1 { Prop[1]: var x } + Diagnostic(ErrorCode.ERR_SyntaxError, "var").WithArguments(",", "").WithLocation(1, 20)); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C1"); + } + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Prop"); + } + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_10() + { + UsingExpression(@"c is [var x]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_11() + { + UsingExpression(@"c is [List]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.TypePattern); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "List"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.GreaterThanToken); + } + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_12() + { + UsingExpression(@"c is [string[]]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.TypePattern); + { + 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.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_13() + { + UsingExpression(@"c is [string[>0]]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.RelationalPattern); + { + N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_14() + { + UsingExpression(@"c is [[_]]"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.DiscardPattern); + { + N(SyntaxKind.UnderscoreToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_15() + { + UsingExpression(@"c is []", + // (1,7): error CS8504: Pattern missing + // c is [] + Diagnostic(ErrorCode.ERR_MissingPattern, "]").WithLocation(1, 7)); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void LengthPattern_16() + { + UsingExpression(@"c is [0]()", + // (1,1): error CS1073: Unexpected token '(' + // c is [0]() + Diagnostic(ErrorCode.ERR_UnexpectedToken, "c is [0]").WithArguments("(").WithLocation(1, 1)); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void NoRegressionOnEmptyPropertyPattern() + { + UsingExpression(@"c is {}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void NoRegressionOnArrayTypePattern() + { + UsingExpression(@"c is string[]"); + + N(SyntaxKind.IsExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + EOF(); + } + + [Fact] + public void ListPattern_01() + { + UsingExpression(@"c is {{}}"); + verify(); + + UsingExpression(@"c is {{}}", TestOptions.Regular9); + verify(); + + void verify() + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + } + + [Fact] + public void ListPattern_02() + { + UsingExpression(@"c is { 1, prop: 0 }"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.NameColon); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "prop"); + } + N(SyntaxKind.ColonToken); + } + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_01() + { + UsingExpression(@"c is {..}"); + verify(); + + UsingExpression(@"c is {..}", TestOptions.Regular9, + // (1,7): error CS8652: The feature 'slice pattern' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // c is {..} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "..").WithArguments("slice pattern").WithLocation(1, 7)); + verify(); + + void verify() + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + } + + [Fact] + public void SlicePattern_02() + { + UsingExpression(@"c is {.. var x}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_03() + { + UsingExpression(@"c is .."); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + } + EOF(); + } + + [Fact] + public void SlicePattern_04() + { + UsingExpression(@"c is ....", + // (1,6): error CS8635: Unexpected character sequence '...' + // c is .... + Diagnostic(ErrorCode.ERR_TripleDotNotAllowed, "").WithLocation(1, 6) + ); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_05() + { + UsingExpression(@"c is {..{}}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_06() + { + UsingExpression(@"c is {.. not p}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.NotPattern); + { + N(SyntaxKind.NotKeyword); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "p"); + } + } + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_07() + { + UsingExpression(@"c is {.. p or q}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.OrPattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "p"); + } + } + } + N(SyntaxKind.OrKeyword); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "q"); + } + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_08() + { + UsingExpression(@"c is {.. p or .. q}"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.OrPattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "p"); + } + } + } + N(SyntaxKind.OrKeyword); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "q"); + } + } + } + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_09() + { + UsingExpression(@"c is .. var x"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_10() + { + UsingExpression(@"c is .. Type"); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Type"); + } + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_11() + { + UsingExpression(@"c is {var x ..}", + // (1,13): error CS1003: Syntax error, ',' expected + // c is {var x ..} + Diagnostic(ErrorCode.ERR_SyntaxError, "..").WithArguments(",", "..").WithLocation(1, 13)); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_12() + { + UsingExpression(@"c is var x ..", + // (1,12): error CS1073: Unexpected token '..' + // c is var x .. + Diagnostic(ErrorCode.ERR_UnexpectedToken, "..").WithArguments("..").WithLocation(1, 12)); + + N(SyntaxKind.RangeExpression); + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + N(SyntaxKind.DotDotToken); + } + EOF(); + } + + [Fact] + public void SlicePattern_13() + { + UsingExpression(@"c is {{}..}", + // (1,9): error CS1003: Syntax error, ',' expected + // c is {{}..} + Diagnostic(ErrorCode.ERR_SyntaxError, "..").WithArguments(",", "..").WithLocation(1, 9)); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.ListPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Subpattern); + { + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_14() + { + UsingExpression(@"c is not p ..", + // (1,13): error CS1001: Identifier expected + // c is not p .. + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 13), + // (1,14): error CS1001: Identifier expected + // c is not p .. + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 14)); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.NotPattern); + { + N(SyntaxKind.NotKeyword); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "p"); + } + N(SyntaxKind.DotToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.DotToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_15() + { + UsingExpression(@"c is not .."); + + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.NotPattern); + { + N(SyntaxKind.NotKeyword); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + } + } + EOF(); + } + + [Fact] + public void SlicePattern_16() + { + UsingExpression(@"c is [..] ..", + // (1,11): error CS1073: Unexpected token '..' + // c is [..] .. + Diagnostic(ErrorCode.ERR_UnexpectedToken, "..").WithArguments("..").WithLocation(1, 11)); + + N(SyntaxKind.RangeExpression); + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.LengthPatternClause); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.SlicePattern); + { + N(SyntaxKind.DotDotToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + } + N(SyntaxKind.DotDotToken); + } + EOF(); + } + + [Fact] + public void SlicePattern_17() + { + UsingExpression(@"c is a .. or b ..", + // (1,9): error CS1001: Identifier expected + // c is a .. or b .. + Diagnostic(ErrorCode.ERR_IdentifierExpected, ".").WithLocation(1, 9), + // (1,16): error CS1073: Unexpected token '..' + // c is a .. or b .. + Diagnostic(ErrorCode.ERR_UnexpectedToken, "..").WithArguments("..").WithLocation(1, 16)); + + N(SyntaxKind.RangeExpression); + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.DeclarationPattern); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.DotToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "or"); + } + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + N(SyntaxKind.DotDotToken); + } + EOF(); + } + + [Fact] + public void SlicePattern_18() + { + UsingExpression(@"c is (var x) .. > 0", + // (1,14): error CS1073: Unexpected token '..' + // c is (var x) .. > 0 + Diagnostic(ErrorCode.ERR_UnexpectedToken, "..").WithArguments("..").WithLocation(1, 14)); + + N(SyntaxKind.GreaterThanExpression); + { + N(SyntaxKind.RangeExpression); + { + N(SyntaxKind.IsPatternExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.IsKeyword); + N(SyntaxKind.ParenthesizedPattern); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.VarPattern); + { + N(SyntaxKind.VarKeyword); + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.DotDotToken); + } + N(SyntaxKind.GreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + EOF(); + } + } +} diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs index a2a1db99543d7..f471533681ae8 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs @@ -48,6 +48,10 @@ public async Task DiagnosticAnalyzerDriverAllInOne() // https://github.com/dotnet/roslyn/issues/44682 - Add to all in one missingSyntaxNodes.Add(SyntaxKind.WithExpression); missingSyntaxNodes.Add(SyntaxKind.RecordDeclaration); + // PROTOTYPE(list-patterns) + missingSyntaxNodes.Add(SyntaxKind.SlicePattern); + missingSyntaxNodes.Add(SyntaxKind.LengthPatternClause); + missingSyntaxNodes.Add(SyntaxKind.ListPatternClause); var analyzer = new CSharpTrackingDiagnosticAnalyzer(); using var workspace = TestWorkspace.CreateCSharp(source, TestOptions.Regular, composition: s_compositionWithMockDiagnosticUpdateSourceRegistrationService); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/PropertySubPatternCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/PropertySubPatternCompletionProvider.cs index 43069af8b68ef..0515cf27b53db 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/PropertySubPatternCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/PropertySubPatternCompletionProvider.cs @@ -124,7 +124,7 @@ private static SyntaxToken TryGetOpenBraceOrCommaInPropertyPatternClause(SyntaxT return default; } - return token.Parent.IsKind(SyntaxKind.PropertyPatternClause) ? token : default; + return token.Parent.IsKind(SyntaxKind.PropertyPatternClause, SyntaxKind.ListPatternClause) ? token : default; } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/FormattingHelpers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/FormattingHelpers.cs index 99a45e3ec9dbe..c0ad5ce49ee3c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/FormattingHelpers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/FormattingHelpers.cs @@ -160,6 +160,7 @@ public static bool IsCloseBraceOfExpression(this SyntaxToken token) return false; } + // PROTOTYPE(list-patterns) SyntaxKind.ListPatternClause return token.Parent is ExpressionSyntax || token.Parent.IsKind(SyntaxKind.PropertyPatternClause); } @@ -330,6 +331,7 @@ public static bool IsCommaInSwitchExpression(this SyntaxToken token) => token.Kind() == SyntaxKind.CommaToken && token.Parent.IsKind(SyntaxKind.SwitchExpression); public static bool IsCommaInPropertyPatternClause(this SyntaxToken token) + // PROTOTYPE(list-patterns) SyntaxKind.ListPatternClause => token.Kind() == SyntaxKind.CommaToken && token.Parent.IsKind(SyntaxKind.PropertyPatternClause); public static bool IsIdentifierInLabeledStatement(this SyntaxToken token) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/BaseFormattingRule.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/BaseFormattingRule.cs index 3d8136fbabfd5..f822c6dc3ea65 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/BaseFormattingRule.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/BaseFormattingRule.cs @@ -180,6 +180,7 @@ protected static void AddBraceSuppressOperations(List list, S // include lambda itself. firstTokenOfNode = node.Parent.GetFirstToken(includeZeroWidth: true); } + // PROTOTYPE(list-patterns) SyntaxKind.ListPatternClause else if (node.IsKind(SyntaxKind.PropertyPatternClause)) { // include the pattern recursive pattern syntax and/or subpattern diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/IndentBlockFormattingRule.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/IndentBlockFormattingRule.cs index 722c935523600..a975d0795f299 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/IndentBlockFormattingRule.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/IndentBlockFormattingRule.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting.Rules; @@ -219,7 +220,7 @@ private void AddBlockIndentationOperation(List list, Synta } // for lambda, set alignment around braces so that users can put brace wherever they want - if (node.IsLambdaBodyBlock() || node.IsAnonymousMethodBlock() || node.IsKind(SyntaxKind.PropertyPatternClause) || node.IsKind(SyntaxKind.SwitchExpression)) + if (node.IsLambdaBodyBlock() || node.IsAnonymousMethodBlock() || node.IsKind(SyntaxKind.PropertyPatternClause, SyntaxKind.ListPatternClause) || node.IsKind(SyntaxKind.SwitchExpression)) { AddAlignmentBlockOperationRelativeToFirstTokenOnBaseTokenLine(list, bracePair); }