From f669d73b48f423b74557086643611476b6b024f2 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 17 Feb 2021 17:47:41 +0330 Subject: [PATCH 01/26] List pattern syntax --- .../CSharp/Portable/CSharpResources.resx | 9 + .../CSharp/Portable/Errors/MessageID.cs | 11 + .../Syntax.xml.Internal.Generated.cs | 422 +++++++++++- .../Syntax.xml.Main.Generated.cs | 63 +- .../Syntax.xml.Syntax.Generated.cs | 123 +++- .../CSharp/Portable/Parser/LanguageParser.cs | 36 +- .../Parser/LanguageParser_Patterns.cs | 52 +- .../CSharp/Portable/PublicAPI.Unshipped.txt | 3 + .../CSharp/Portable/Syntax/Syntax.xml | 44 +- .../CSharp/Portable/Syntax/SyntaxKind.cs | 4 + .../Generated/Syntax.Test.xml.Generated.cs | 174 ++++- .../Syntax/Parsing/PatternParsingTests.cs | 2 +- .../Syntax/Parsing/PatternParsingTests2.cs | 601 ++++++++++++++++++ .../Core/Portable/Diagnostic/DiagnosticBag.cs | 14 + 14 files changed, 1486 insertions(+), 72 deletions(-) create mode 100644 src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 92bed07080910..e894307bef1f2 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6600,4 +6600,13 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Using a function pointer type in a 'typeof' in an attribute is not supported. + + list pattern + + + slice pattern + + + length pattern + diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index b9399edf14c78..1d6fb2262144b 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, @@ -489,6 +494,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/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index 7a4108972ee84..9f0c24bb2de85 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,131 @@ 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; + if (pattern != null) + { + 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; + if (pattern != null) + { + 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; + if (pattern != null) + { + 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(); + if (pattern != null) + { + 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 +10979,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 +11737,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 +33304,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 +33314,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 +33541,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 +33551,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 +33948,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 +33980,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 +36288,34 @@ 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 (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 +36340,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 +36356,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 +36532,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 +41205,34 @@ 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, propertyPatternClause, designation); + 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 (closeBracketToken == null) throw new ArgumentNullException(nameof(closeBracketToken)); + if (closeBracketToken.Kind != SyntaxKind.CloseBracketToken) throw new ArgumentException(nameof(closeBracketToken)); +#endif + + 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 +41257,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 +41273,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 +41449,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 +44319,7 @@ internal static IEnumerable GetNodeTypes() typeof(DeclarationPatternSyntax), typeof(VarPatternSyntax), typeof(RecursivePatternSyntax), + typeof(LengthPatternClauseSyntax), typeof(PositionalPatternClauseSyntax), typeof(PropertyPatternClauseSyntax), typeof(SubpatternSyntax), @@ -43960,6 +44329,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..325b88bb64aa2 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), 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,26 @@ 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 (closeBracketToken.Kind() != SyntaxKind.CloseBracketToken) throw new ArgumentException(nameof(closeBracketToken)); + return (LengthPatternClauseSyntax)Syntax.InternalSyntax.SyntaxFactory.LengthPatternClause((Syntax.InternalSyntax.SyntaxToken)openBracketToken.Node!, pattern == null ? null : (Syntax.InternalSyntax.PatternSyntax)pattern.Green, (Syntax.InternalSyntax.SyntaxToken)closeBracketToken.Node!).CreateRed(); + } + + /// Creates a new LengthPatternClauseSyntax instance. + public static LengthPatternClauseSyntax LengthPatternClause(PatternSyntax? pattern = default) + => 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 +3604,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 +3720,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..c4a0b666dd418 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) { - var propertyPatternClause = this.PropertyPatternClause ?? SyntaxFactory.PropertyPatternClause(); - return WithPropertyPatternClause(propertyPatternClause.WithSubpatterns(propertyPatternClause.Subpatterns.AddRange(items))); } + + 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) + { + 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/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 05249fd4615e3..ea660e9c75578 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6706,17 +6706,47 @@ bool canBeNullableType() continue; } goto done; // token not consumed + case SyntaxKind.OpenBracketToken when (nameOptions & NameOptions.PossiblePattern) != 0: + // We don't want to consume a sized rank specifier in patterns, we leave it out to parse it as a length pattern. + { + if (isOmittedSize()) + { + bool sawOpenBracket; + var ranks = _pool.Allocate(); + try + { + do + { + ranks.Add(this.ParseArrayRankSpecifier(out _)); + } + while ((sawOpenBracket = this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) && isOmittedSize()); + + type = _syntaxFactory.ArrayType(type, ranks); + } + finally + { + _pool.Free(ranks); + } + + // If we saw an open bracket that is not followed by an ommited size, it's possibly a length pattern. + if (!sawOpenBracket) + continue; + } + goto done; + + bool isOmittedSize() => this.PeekToken(1).Kind is SyntaxKind.CommaToken or SyntaxKind.CloseBracketToken; + } case SyntaxKind.OpenBracketToken: // Now check for arrays. { var ranks = _pool.Allocate(); try { - while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) + do { - var rank = this.ParseArrayRankSpecifier(out _); - ranks.Add(rank); + ranks.Add(this.ParseArrayRankSpecifier(out _)); } + while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken); type = _syntaxFactory.ArrayType(type, ranks); } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 2e6b9ecae1980..73fc359acfa84 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -8,6 +8,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax { + using System; using Microsoft.CodeAnalysis.Syntax.InternalSyntax; internal partial class LanguageParser : SyntaxParser @@ -207,6 +208,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: false) : null); case SyntaxKind.LessThanToken: case SyntaxKind.LessThanEqualsToken: case SyntaxKind.GreaterThanToken: @@ -303,7 +308,7 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden openKind: SyntaxKind.OpenParenToken, closeKind: SyntaxKind.CloseParenToken); - parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0); + parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0, afterLengthPattern: false); parseDesignation(out VariableDesignationSyntax designation0); if (type == null && @@ -330,14 +335,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, lengthPatternClause: null, propertyPatternClause0, designation0); return result; } - if (parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause)) + if (parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause) | + parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause, afterLengthPattern: lengthPatternClause is not null)) { 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,12 +369,23 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden // let the caller fall back to parsing an expression return null; - bool parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClauseResult) + bool parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause) + { + if (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) + { + lengthPatternClause = ParseLengthPatternClause(); + return true; + } + lengthPatternClause = null; + return false; + } + + bool parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClauseResult, bool afterLengthPattern) { propertyPatternClauseResult = null; if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) { - propertyPatternClauseResult = ParsePropertyPatternClause(); + propertyPatternClauseResult = ParsePropertyPatternClause(afterLengthPattern); return true; } @@ -397,6 +414,15 @@ bool looksLikeCast() } } + private LengthPatternClauseSyntax ParseLengthPatternClause() + { + var openBracket = EatToken(SyntaxKind.OpenBracketToken); + var pattern = IsPossibleSubpatternElement() ? ParsePattern(Precedence.Conditional) : null; + 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) @@ -504,7 +530,7 @@ private bool LooksLikeTupleArrayType() } } - private PropertyPatternClauseSyntax ParsePropertyPatternClause() + private PropertyPatternClauseSyntax ParsePropertyPatternClause(bool afterLengthPattern) { ParseSubpatternList( openToken: out SyntaxToken openBraceToken, @@ -512,7 +538,10 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause() closeToken: out SyntaxToken closeBraceToken, openKind: SyntaxKind.OpenBraceToken, closeKind: SyntaxKind.CloseBraceToken); - return _syntaxFactory.PropertyPatternClause(openBraceToken, subPatterns, closeBraceToken); + var kind = afterLengthPattern || subPatterns.Count > 0 && subPatterns[0].NameColon is null + ? SyntaxKind.ListPatternClause + : SyntaxKind.PropertyPatternClause; + return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken); } private void ParseSubpatternList( @@ -522,9 +551,9 @@ private void ParseSubpatternList( SyntaxKind openKind, SyntaxKind closeKind) { - 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); openToken = this.EatToken(openKind); @@ -603,6 +632,7 @@ private bool IsPossibleSubpatternElement() this.CurrentToken.Kind switch { SyntaxKind.OpenBraceToken => true, + SyntaxKind.OpenBracketToken => true, SyntaxKind.LessThanToken => true, SyntaxKind.LessThanEqualsToken => true, SyntaxKind.GreaterThanToken => true, diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 47fdde3be2e2f..2ecb8ddd7be65 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.LengthPatternClause = 9035 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.ListPatternClause = 9036 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.SlicePattern = 9034 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index f24059e17aa41..842b27860880d 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1998,16 +1998,50 @@ + - + + + + + + + + + + + + + @@ -2020,6 +2054,7 @@ + @@ -2093,6 +2128,13 @@ + + + + + + + diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 4686c56198157..2c67ce512632e 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -827,6 +827,10 @@ public enum SyntaxKind : ushort AndPattern = 9032, NotPattern = 9033, + SlicePattern = 9034, + LengthPatternClause = 9035, + ListPatternClause = 9036, + // Kinds between 9000 and 9039 are "reserved" for pattern matching. DeclarationExpression = 9040, 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..ddfd728c6aa47 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), null, 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.Null(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), default(PatternSyntax), 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.Null(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 55e631190e496..9d8d46b97a47c 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/PatternParsingTests2.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs new file mode 100644 index 0000000000000..36528775267f5 --- /dev/null +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs @@ -0,0 +1,601 @@ +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class PatternParsingTests2 : ParsingTests + { + private new void UsingExpression(string text, params DiagnosticDescription[] expectedErrors) + { + UsingExpression(text, options: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview), expectedErrors); + } + + public PatternParsingTests2(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void LengthPattern_01() + { + UsingExpression(@"c is []{}"); + verify(); + + UsingExpression(@"c is []{}", 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 []{} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "[]").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.CloseBracketToken); + } + N(SyntaxKind.ListPatternClause); + { + 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.ListPatternClause); + { + 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 ()[]", + // (1,1): error CS1073: Unexpected token '[' + // c is ()[] + Diagnostic(ErrorCode.ERR_UnexpectedToken, "c is ()").WithArguments("[").WithLocation(1, 1) + ); + + 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); + } + } + } + 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 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 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 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(); + } + } +} diff --git a/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs b/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs index 43af33b7d544e..32d1416f29651 100644 --- a/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs +++ b/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs @@ -8,6 +8,7 @@ using System.Collections; using System.Collections.Immutable; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Text; using System.Threading; using Microsoft.CodeAnalysis.PooledObjects; @@ -333,6 +334,19 @@ private static ObjectPool CreatePool(int size) return new ObjectPool(() => new DiagnosticBag(), size); } + internal static Disposer GetInstance(out DiagnosticBag bag) + { + bag = GetInstance(); + return new Disposer(bag); + } + + internal readonly ref struct Disposer + { + private readonly DiagnosticBag _bag; + public Disposer(DiagnosticBag bag) => _bag = bag; + public void Dispose() => _bag.Free(); + } + #endregion #region Debugger View From 2340d9adfac8da5e1f2840ea0ac92672600a6265 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Thu, 18 Feb 2021 08:09:29 +0330 Subject: [PATCH 02/26] Update resources --- .../CSharp/Portable/xlf/CSharpResources.cs.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.de.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.es.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.fr.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.it.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.ja.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.ko.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.pl.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.pt-BR.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.ru.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.tr.xlf | 15 +++++++++++++++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 15 +++++++++++++++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 15 +++++++++++++++ 13 files changed, 195 insertions(+) diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index e59d0378498e5..57d09788d64c9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -967,6 +967,21 @@ Vytvoření objektu s cílovým typem + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 a7f7daf9c9531..078d655b9279f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -967,6 +967,21 @@ Objekterstellung mit Zieltyp + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 bf8254701b669..da79c7ad3f79a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -967,6 +967,21 @@ creación de objetos con tipo de destino + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 27851497d9563..0027ed934157a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -967,6 +967,21 @@ création d'un objet typé cible + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 8e618c1df1719..adf70a54e07b2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -967,6 +967,21 @@ creazione di oggetti con tipo di destinazione + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 b3e7c9c2ea654..3a15572f478b2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -967,6 +967,21 @@ target-typed オブジェクトの作成 + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 b85ec5a5945db..1e11bc15cfa11 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -967,6 +967,21 @@ 대상으로 형식화된 개체 만들기 + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 e4ffe0585be1f..58e095b660110 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -967,6 +967,21 @@ tworzenie obiektu z typem docelowym + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 96850ee838524..9d0f25e21f6cb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -967,6 +967,21 @@ criação de objeto de tipo de destino + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 2c3eac72f5f74..25fc147990704 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -967,6 +967,21 @@ создание объекта с типом целевого объекта + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 f22b18b12866e..2900958ff8d4c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -967,6 +967,21 @@ hedeflenen türde nesne oluşturma + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 4c5590fec058c..b524c26f30b4d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -967,6 +967,21 @@ 创建目标类型对象 + + length pattern + length pattern + + + + list pattern + list pattern + + + + 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 3761d02b61a95..8a0964a3c4226 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -967,6 +967,21 @@ 建立具目標類型的物件 + + length pattern + length pattern + + + + list pattern + list pattern + + + + slice pattern + slice pattern + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 包含類型 '{1}' 的組件 '{0}' 參考了 .NET Framework,此情形不受支援。 From 589dbd16a4e5d5435cd488aa69bd7a2dda5e380c Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Thu, 18 Feb 2021 08:49:21 +0330 Subject: [PATCH 03/26] Revert code --- src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 73fc359acfa84..7fbc599ab887c 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -8,7 +8,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax { - using System; using Microsoft.CodeAnalysis.Syntax.InternalSyntax; internal partial class LanguageParser : SyntaxParser From 4708beac9bd17343569d70217bc6ee1cd38e09ed Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Thu, 18 Feb 2021 08:56:00 +0330 Subject: [PATCH 04/26] Revert code --- .../Core/Portable/Diagnostic/DiagnosticBag.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs b/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs index 32d1416f29651..43af33b7d544e 100644 --- a/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs +++ b/src/Compilers/Core/Portable/Diagnostic/DiagnosticBag.cs @@ -8,7 +8,6 @@ using System.Collections; using System.Collections.Immutable; using System.Diagnostics; -using System.Runtime.CompilerServices; using System.Text; using System.Threading; using Microsoft.CodeAnalysis.PooledObjects; @@ -334,19 +333,6 @@ private static ObjectPool CreatePool(int size) return new ObjectPool(() => new DiagnosticBag(), size); } - internal static Disposer GetInstance(out DiagnosticBag bag) - { - bag = GetInstance(); - return new Disposer(bag); - } - - internal readonly ref struct Disposer - { - private readonly DiagnosticBag _bag; - public Disposer(DiagnosticBag bag) => _bag = bag; - public void Dispose() => _bag.Free(); - } - #endregion #region Debugger View From 6de5e2d9db7c257706ed9a0aa1e3bdde3a78ad87 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Thu, 18 Feb 2021 09:07:43 +0330 Subject: [PATCH 05/26] Fix typo --- src/Compilers/CSharp/Portable/Parser/LanguageParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index ea660e9c75578..2cde7a4414be8 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6728,7 +6728,7 @@ bool canBeNullableType() _pool.Free(ranks); } - // If we saw an open bracket that is not followed by an ommited size, it's possibly a length pattern. + // If we saw an open bracket that is not followed by an omitted size, it's possibly a length pattern. if (!sawOpenBracket) continue; } From 5fa18bb64e8676b2eb4f2dc244e94617ede25f3a Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 27 Feb 2021 20:04:17 +0330 Subject: [PATCH 06/26] Adjust parsing to the confirmed syntax --- .editorconfig | 3 + .../Portable/Generated/CSharp.Generated.g4 | 11 ++- .../Syntax.xml.Internal.Generated.cs | 72 +++++++------------ .../Syntax.xml.Main.Generated.cs | 23 +++--- .../Syntax.xml.Syntax.Generated.cs | 16 +++-- .../Parser/LanguageParser_Patterns.cs | 20 +++--- .../CSharp/Portable/Syntax/Syntax.xml | 26 +------ .../CSharp/Portable/Syntax/SyntaxKind.cs | 1 - .../Generated/Syntax.Test.xml.Generated.cs | 12 ++-- .../Syntax/Parsing/PatternParsingTests.cs | 2 +- ...cs => PatternParsingTests_ListPatterns.cs} | 51 ++++++++----- 11 files changed, 107 insertions(+), 130 deletions(-) rename src/Compilers/CSharp/Test/Syntax/Parsing/{PatternParsingTests2.cs => PatternParsingTests_ListPatterns.cs} (91%) diff --git a/.editorconfig b/.editorconfig index 6d966e98ae243..317c94e5c2f64 100644 --- a/.editorconfig +++ b/.editorconfig @@ -163,6 +163,9 @@ dotnet_diagnostic.IDE0044.severity = warning # RS0016: Only enable if API files are present dotnet_public_api_analyzer.require_api_files = true +# PROTOTYPE(list-patterns) https://github.com/dotnet/roslyn/issues/50357 +dotnet_public_api_analyzer.severity = none + # CSharp code style settings: [*.cs] # Newline settings 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 9f0c24bb2de85..a69557512cc4e 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 @@ -10658,57 +10658,48 @@ static RecursivePatternSyntax() internal sealed partial class LengthPatternClauseSyntax : CSharpSyntaxNode { internal readonly SyntaxToken openBracketToken; - internal readonly PatternSyntax? pattern; + internal readonly PatternSyntax pattern; internal readonly SyntaxToken closeBracketToken; - internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax? pattern, SyntaxToken closeBracketToken, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + 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; - if (pattern != null) - { - this.AdjustFlagsAndWidth(pattern); - this.pattern = pattern; - } + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; this.AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; } - internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax? pattern, SyntaxToken closeBracketToken, SyntaxFactoryContext context) + 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; - if (pattern != null) - { - this.AdjustFlagsAndWidth(pattern); - this.pattern = pattern; - } + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; this.AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; } - internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax? pattern, SyntaxToken closeBracketToken) + internal LengthPatternClauseSyntax(SyntaxKind kind, SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) : base(kind) { this.SlotCount = 3; this.AdjustFlagsAndWidth(openBracketToken); this.openBracketToken = openBracketToken; - if (pattern != null) - { - this.AdjustFlagsAndWidth(pattern); - this.pattern = pattern; - } + this.AdjustFlagsAndWidth(pattern); + this.pattern = pattern; this.AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; } public SyntaxToken OpenBracketToken => this.openBracketToken; - public PatternSyntax? Pattern => this.pattern; + public PatternSyntax Pattern => this.pattern; public SyntaxToken CloseBracketToken => this.closeBracketToken; internal override GreenNode? GetSlot(int index) @@ -10755,12 +10746,9 @@ internal LengthPatternClauseSyntax(ObjectReader reader) var openBracketToken = (SyntaxToken)reader.ReadValue(); AdjustFlagsAndWidth(openBracketToken); this.openBracketToken = openBracketToken; - var pattern = (PatternSyntax?)reader.ReadValue(); - if (pattern != null) - { - AdjustFlagsAndWidth(pattern); - this.pattern = pattern; - } + var pattern = (PatternSyntax)reader.ReadValue(); + AdjustFlagsAndWidth(pattern); + this.pattern = pattern; var closeBracketToken = (SyntaxToken)reader.ReadValue(); AdjustFlagsAndWidth(closeBracketToken); this.closeBracketToken = closeBracketToken; @@ -10979,7 +10967,7 @@ public PropertyPatternClauseSyntax Update(SyntaxToken openBraceToken, Microsoft. { if (openBraceToken != this.OpenBraceToken || subpatterns != this.Subpatterns || closeBraceToken != this.CloseBraceToken) { - var newNode = SyntaxFactory.PropertyPatternClause(this.Kind, openBraceToken, subpatterns, closeBraceToken); + var newNode = SyntaxFactory.PropertyPatternClause(openBraceToken, subpatterns, closeBraceToken); var diags = GetDiagnostics(); if (diags?.Length > 0) newNode = newNode.WithDiagnosticsGreen(diags); @@ -36296,11 +36284,12 @@ public RecursivePatternSyntax RecursivePattern(TypeSyntax? type, PositionalPatte return new RecursivePatternSyntax(SyntaxKind.RecursivePattern, type, positionalPatternClause, lengthPatternClause, propertyPatternClause, designation, this.context); } - public LengthPatternClauseSyntax LengthPatternClause(SyntaxToken openBracketToken, PatternSyntax? pattern, SyntaxToken closeBracketToken) + 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 @@ -36340,14 +36329,8 @@ public PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken openPar return result; } - public PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + public PropertyPatternClauseSyntax PropertyPatternClause(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)); @@ -36356,10 +36339,10 @@ public PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, Syntax #endif int hash; - var cached = CSharpSyntaxNodeCache.TryGetNode((int)kind, openBraceToken, subpatterns.Node, closeBraceToken, this.context, out hash); + var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken, this.context, out hash); if (cached != null) return (PropertyPatternClauseSyntax)cached; - var result = new PropertyPatternClauseSyntax(kind, openBraceToken, subpatterns.Node, closeBraceToken, this.context); + var result = new PropertyPatternClauseSyntax(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken, this.context); if (hash >= 0) { SyntaxNodeCache.AddNode(result, hash); @@ -41213,11 +41196,12 @@ public static RecursivePatternSyntax RecursivePattern(TypeSyntax? type, Position return new RecursivePatternSyntax(SyntaxKind.RecursivePattern, type, positionalPatternClause, lengthPatternClause, propertyPatternClause, designation); } - public static LengthPatternClauseSyntax LengthPatternClause(SyntaxToken openBracketToken, PatternSyntax? pattern, SyntaxToken closeBracketToken) + 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 @@ -41257,14 +41241,8 @@ public static PositionalPatternClauseSyntax PositionalPatternClause(SyntaxToken return result; } - public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + public static PropertyPatternClauseSyntax PropertyPatternClause(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)); @@ -41273,10 +41251,10 @@ public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, #endif int hash; - var cached = SyntaxNodeCache.TryGetNode((int)kind, openBraceToken, subpatterns.Node, closeBraceToken, out hash); + var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken, out hash); if (cached != null) return (PropertyPatternClauseSyntax)cached; - var result = new PropertyPatternClauseSyntax(kind, openBraceToken, subpatterns.Node, closeBraceToken); + var result = new PropertyPatternClauseSyntax(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns.Node, closeBraceToken); if (hash >= 0) { SyntaxNodeCache.AddNode(result, hash); 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 325b88bb64aa2..6e986f226add9 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 @@ -1678,7 +1678,7 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor => 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), VisitToken(node.CloseBracketToken)); + => 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)); @@ -3580,15 +3580,16 @@ public static RecursivePatternSyntax RecursivePattern() => SyntaxFactory.RecursivePattern(default, default, default, default, default); /// Creates a new LengthPatternClauseSyntax instance. - public static LengthPatternClauseSyntax LengthPatternClause(SyntaxToken openBracketToken, PatternSyntax? pattern, SyntaxToken closeBracketToken) + 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!, pattern == null ? null : (Syntax.InternalSyntax.PatternSyntax)pattern.Green, (Syntax.InternalSyntax.SyntaxToken)closeBracketToken.Node!).CreateRed(); + 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 = default) + public static LengthPatternClauseSyntax LengthPatternClause(PatternSyntax pattern) => SyntaxFactory.LengthPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), pattern, SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); /// Creates a new PositionalPatternClauseSyntax instance. @@ -3604,22 +3605,16 @@ 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(SyntaxKind kind, SyntaxToken openBraceToken, SeparatedSyntaxList subpatterns, SyntaxToken closeBraceToken) + public static PropertyPatternClauseSyntax PropertyPatternClause(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(kind, (Syntax.InternalSyntax.SyntaxToken)openBraceToken.Node!, subpatterns.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)closeBraceToken.Node!).CreateRed(); + return (PropertyPatternClauseSyntax)Syntax.InternalSyntax.SyntaxFactory.PropertyPatternClause((Syntax.InternalSyntax.SyntaxToken)openBraceToken.Node!, subpatterns.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)closeBraceToken.Node!).CreateRed(); } /// Creates a new PropertyPatternClauseSyntax instance. - public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxKind kind, SeparatedSyntaxList subpatterns = default) - => SyntaxFactory.PropertyPatternClause(kind, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), subpatterns, SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + public static PropertyPatternClauseSyntax PropertyPatternClause(SeparatedSyntaxList subpatterns = default) + => SyntaxFactory.PropertyPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBraceToken), subpatterns, SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); /// Creates a new SubpatternSyntax instance. public static SubpatternSyntax Subpattern(NameColonSyntax? nameColon, PatternSyntax pattern) 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 c4a0b666dd418..9dd2744fe328b 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 @@ -5082,6 +5082,11 @@ public RecursivePatternSyntax AddPositionalPatternClauseSubpatterns(params Subpa var positionalPatternClause = this.PositionalPatternClause ?? SyntaxFactory.PositionalPatternClause(); return WithPositionalPatternClause(positionalPatternClause.WithSubpatterns(positionalPatternClause.Subpatterns.AddRange(items))); } + public RecursivePatternSyntax AddPropertyPatternClauseSubpatterns(params SubpatternSyntax[] items) + { + var propertyPatternClause = this.PropertyPatternClause ?? SyntaxFactory.PropertyPatternClause(); + return WithPropertyPatternClause(propertyPatternClause.WithSubpatterns(propertyPatternClause.Subpatterns.AddRange(items))); + } } /// @@ -5101,18 +5106,18 @@ internal LengthPatternClauseSyntax(InternalSyntax.CSharpSyntaxNode green, Syntax public SyntaxToken OpenBracketToken => new SyntaxToken(this, ((Syntax.InternalSyntax.LengthPatternClauseSyntax)this.Green).openBracketToken, Position, 0); - public PatternSyntax? Pattern => GetRed(ref this.pattern, 1); + 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? 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) + public LengthPatternClauseSyntax Update(SyntaxToken openBracketToken, PatternSyntax pattern, SyntaxToken closeBracketToken) { if (openBracketToken != this.OpenBracketToken || pattern != this.Pattern || closeBracketToken != this.CloseBracketToken) { @@ -5125,7 +5130,7 @@ public LengthPatternClauseSyntax Update(SyntaxToken openBracketToken, PatternSyn } public LengthPatternClauseSyntax WithOpenBracketToken(SyntaxToken openBracketToken) => Update(openBracketToken, this.Pattern, this.CloseBracketToken); - public LengthPatternClauseSyntax WithPattern(PatternSyntax? pattern) => Update(this.OpenBracketToken, 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); } @@ -5187,7 +5192,6 @@ public PositionalPatternClauseSyntax Update(SyntaxToken openParenToken, Separate /// This node is associated with the following syntax kinds: /// /// - /// /// /// public sealed partial class PropertyPatternClauseSyntax : CSharpSyntaxNode @@ -5223,7 +5227,7 @@ public PropertyPatternClauseSyntax Update(SyntaxToken openBraceToken, SeparatedS { if (openBraceToken != this.OpenBraceToken || subpatterns != this.Subpatterns || closeBraceToken != this.CloseBraceToken) { - var newNode = SyntaxFactory.PropertyPatternClause(this.Kind(), openBraceToken, subpatterns, closeBraceToken); + var newNode = SyntaxFactory.PropertyPatternClause(openBraceToken, subpatterns, closeBraceToken); var annotations = GetAnnotations(); return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 7fbc599ab887c..ff9334b61712a 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -307,7 +307,8 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden openKind: SyntaxKind.OpenParenToken, closeKind: SyntaxKind.CloseParenToken); - parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0, afterLengthPattern: false); + parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause0); + parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0); parseDesignation(out VariableDesignationSyntax designation0); if (type == null && @@ -334,12 +335,12 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden } var positionalPatternClause = _syntaxFactory.PositionalPatternClause(openParenToken, subPatterns, closeParenToken); - var result = _syntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause: null, propertyPatternClause0, designation0); + var result = _syntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause: lengthPatternClause0, propertyPatternClause0, designation0); return result; } if (parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause) | - parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause, afterLengthPattern: lengthPatternClause is not null)) + parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause)) { parseDesignation(out VariableDesignationSyntax designation0); return _syntaxFactory.RecursivePattern(type, positionalPatternClause: null, lengthPatternClause, propertyPatternClause, designation0); @@ -379,12 +380,12 @@ bool parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause) return false; } - bool parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClauseResult, bool afterLengthPattern) + bool parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClauseResult) { propertyPatternClauseResult = null; if (this.CurrentToken.Kind == SyntaxKind.OpenBraceToken) { - propertyPatternClauseResult = ParsePropertyPatternClause(afterLengthPattern); + propertyPatternClauseResult = ParsePropertyPatternClause(); return true; } @@ -416,7 +417,7 @@ bool looksLikeCast() private LengthPatternClauseSyntax ParseLengthPatternClause() { var openBracket = EatToken(SyntaxKind.OpenBracketToken); - var pattern = IsPossibleSubpatternElement() ? ParsePattern(Precedence.Conditional) : null; + var pattern = ParsePattern(Precedence.Conditional); var closeBracket = EatToken(SyntaxKind.CloseBracketToken); var result = _syntaxFactory.LengthPatternClause(openBracket, pattern, closeBracket); return CheckFeatureAvailability(result, MessageID.IDS_FeatureLengthPattern); @@ -529,7 +530,7 @@ private bool LooksLikeTupleArrayType() } } - private PropertyPatternClauseSyntax ParsePropertyPatternClause(bool afterLengthPattern) + private PropertyPatternClauseSyntax ParsePropertyPatternClause() { ParseSubpatternList( openToken: out SyntaxToken openBraceToken, @@ -537,10 +538,7 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause(bool afterLengthP closeToken: out SyntaxToken closeBraceToken, openKind: SyntaxKind.OpenBraceToken, closeKind: SyntaxKind.CloseBraceToken); - var kind = afterLengthPattern || subPatterns.Count > 0 && subPatterns[0].NameColon is null - ? SyntaxKind.ListPatternClause - : SyntaxKind.PropertyPatternClause; - return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken); + return _syntaxFactory.PropertyPatternClause(openBraceToken, subPatterns, closeBraceToken); } private void ParseSubpatternList( diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 842b27860880d..dc9cd26dad0ca 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1998,34 +1998,11 @@ - - @@ -2037,7 +2014,7 @@ - + @@ -2054,7 +2031,6 @@ - diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 2c67ce512632e..f7d8163ad9868 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -829,7 +829,6 @@ public enum SyntaxKind : ushort SlicePattern = 9034, LengthPatternClause = 9035, - ListPatternClause = 9036, // Kinds between 9000 and 9039 are "reserved" for pattern matching. 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 ddfd728c6aa47..1403f914aebc3 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 @@ -269,13 +269,13 @@ private static Syntax.InternalSyntax.RecursivePatternSyntax GenerateRecursivePat => InternalSyntaxFactory.RecursivePattern(null, null, null, null, null); private static Syntax.InternalSyntax.LengthPatternClauseSyntax GenerateLengthPatternClause() - => InternalSyntaxFactory.LengthPatternClause(InternalSyntaxFactory.Token(SyntaxKind.OpenBracketToken), null, InternalSyntaxFactory.Token(SyntaxKind.CloseBracketToken)); + => 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(SyntaxKind.PropertyPatternClause, InternalSyntaxFactory.Token(SyntaxKind.OpenBraceToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + => InternalSyntaxFactory.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()); @@ -1738,7 +1738,7 @@ public void TestLengthPatternClauseFactoryAndProperties() var node = GenerateLengthPatternClause(); Assert.Equal(SyntaxKind.OpenBracketToken, node.OpenBracketToken.Kind); - Assert.Null(node.Pattern); + Assert.NotNull(node.Pattern); Assert.Equal(SyntaxKind.CloseBracketToken, node.CloseBracketToken.Kind); AttachAndCheckDiagnostics(node); @@ -10014,13 +10014,13 @@ private static RecursivePatternSyntax GenerateRecursivePattern() => SyntaxFactory.RecursivePattern(default(TypeSyntax), default(PositionalPatternClauseSyntax), default(LengthPatternClauseSyntax), default(PropertyPatternClauseSyntax), default(VariableDesignationSyntax)); private static LengthPatternClauseSyntax GenerateLengthPatternClause() - => SyntaxFactory.LengthPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), default(PatternSyntax), SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); + => 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(SyntaxKind.PropertyPatternClause, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); + => SyntaxFactory.PropertyPatternClause(SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); private static SubpatternSyntax GenerateSubpattern() => SyntaxFactory.Subpattern(default(NameColonSyntax), GenerateDiscardPattern()); @@ -11483,7 +11483,7 @@ public void TestLengthPatternClauseFactoryAndProperties() var node = GenerateLengthPatternClause(); Assert.Equal(SyntaxKind.OpenBracketToken, node.OpenBracketToken.Kind()); - Assert.Null(node.Pattern); + 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); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs index 9d8d46b97a47c..55e631190e496 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.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); M(SyntaxKind.Subpattern); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs similarity index 91% rename from src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs rename to src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs index 36528775267f5..208194a39504f 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests2.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -5,27 +5,27 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { - public class PatternParsingTests2 : ParsingTests + public class PatternParsingTests_ListPatterns : ParsingTests { private new void UsingExpression(string text, params DiagnosticDescription[] expectedErrors) { UsingExpression(text, options: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview), expectedErrors); } - public PatternParsingTests2(ITestOutputHelper output) : base(output) + public PatternParsingTests_ListPatterns(ITestOutputHelper output) : base(output) { } [Fact] public void LengthPattern_01() { - UsingExpression(@"c is []{}"); + UsingExpression(@"c is [0]{}"); verify(); - UsingExpression(@"c is []{}", TestOptions.Regular9, + 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 []{} - Diagnostic(ErrorCode.ERR_FeatureInPreview, "[]").WithArguments("length pattern").WithLocation(1, 6)); + // c is [0]{} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "[0]").WithArguments("length pattern").WithLocation(1, 6)); verify(); void verify() @@ -42,9 +42,16 @@ void verify() N(SyntaxKind.LengthPatternClause); { N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.ConstantPattern); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.CloseBraceToken); @@ -110,7 +117,7 @@ public void LengthPattern_03() } N(SyntaxKind.CloseBracketToken); } - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -141,11 +148,7 @@ public void LengthPattern_03() [Fact] public void LengthPattern_04() { - UsingExpression(@"c is ()[]", - // (1,1): error CS1073: Unexpected token '[' - // c is ()[] - Diagnostic(ErrorCode.ERR_UnexpectedToken, "c is ()").WithArguments("[").WithLocation(1, 1) - ); + UsingExpression(@"c is ()[0]"); N(SyntaxKind.IsPatternExpression); { @@ -161,6 +164,18 @@ public void LengthPattern_04() 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(); @@ -367,7 +382,7 @@ void verify() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -412,7 +427,7 @@ void verify() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -444,7 +459,7 @@ public void SlicePattern_02() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -531,7 +546,7 @@ public void SlicePattern_05() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -570,7 +585,7 @@ public void SlicePattern_06() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.ListPatternClause); + N(SyntaxKind.PropertyPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); From 39f8a6f9090f2be833ebd104a23ebe4b06a2843e Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 27 Feb 2021 20:23:14 +0330 Subject: [PATCH 07/26] Simplify --- .../Portable/Parser/LanguageParser_Patterns.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index ff9334b61712a..ac9e3856140c3 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -626,16 +626,13 @@ private SubpatternSyntax ParseSubpatternElement() private bool IsPossibleSubpatternElement() { return this.IsPossibleExpression(allowBinaryExpressions: false, allowAssignmentExpressions: false) || - this.CurrentToken.Kind switch - { - SyntaxKind.OpenBraceToken => true, - SyntaxKind.OpenBracketToken => 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( From d6be7be4cf4e0e9c75927e020e7e4766945d439b Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 27 Feb 2021 20:31:43 +0330 Subject: [PATCH 08/26] Revert whitespace --- src/Compilers/CSharp/Portable/Syntax/Syntax.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index dc9cd26dad0ca..dff818f5a8371 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -2003,7 +2003,7 @@ - + From fdc50a05afd7a6d439af6b583a9e76f9d4db58ec Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 27 Feb 2021 20:55:37 +0330 Subject: [PATCH 09/26] Disable PublicApi diagnostics --- .editorconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 317c94e5c2f64..21f40d874118e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -164,7 +164,9 @@ dotnet_diagnostic.IDE0044.severity = warning dotnet_public_api_analyzer.require_api_files = true # PROTOTYPE(list-patterns) https://github.com/dotnet/roslyn/issues/50357 -dotnet_public_api_analyzer.severity = none +dotnet_diagnostic.RS0016.severity = none +dotnet_diagnostic.RS0017.severity = none +dotnet_diagnostic.RS0027.severity = none # CSharp code style settings: [*.cs] From 0b2c4c44fc579f1a15c6a2efffd43ec926a6ffed Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 20 Mar 2021 12:11:25 +0330 Subject: [PATCH 10/26] Attempt to disable RS0016 --- .editorconfig | 5 ---- eng/targets/Settings.props | 3 +- .../CSharp/Portable/PublicAPI.Unshipped.txt | 1 - .../Portable/Syntax/RecursivePatternSyntax.cs | 29 +++++++++++++++++++ 4 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs diff --git a/.editorconfig b/.editorconfig index 21f40d874118e..6d966e98ae243 100644 --- a/.editorconfig +++ b/.editorconfig @@ -163,11 +163,6 @@ dotnet_diagnostic.IDE0044.severity = warning # RS0016: Only enable if API files are present dotnet_public_api_analyzer.require_api_files = true -# PROTOTYPE(list-patterns) https://github.com/dotnet/roslyn/issues/50357 -dotnet_diagnostic.RS0016.severity = none -dotnet_diagnostic.RS0017.severity = none -dotnet_diagnostic.RS0027.severity = none - # CSharp code style settings: [*.cs] # Newline settings diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props index c20014e29fc6b..b075f74b49f4f 100644 --- a/eng/targets/Settings.props +++ b/eng/targets/Settings.props @@ -212,7 +212,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/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 2ecb8ddd7be65..24e8e4ee5be7e 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1,4 +1,3 @@ override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetUsedAssemblyReferences(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.CSharp.SyntaxKind.LengthPatternClause = 9035 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind -Microsoft.CodeAnalysis.CSharp.SyntaxKind.ListPatternClause = 9036 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.SlicePattern = 9034 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind diff --git a/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs new file mode 100644 index 0000000000000..7a6319aa0b6e5 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs @@ -0,0 +1,29 @@ +// 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, lengthPatternClause: null, propertyPatternClause, designation); + } + } +} + +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); + } + } +} From b2471d55ee7b3d883c35fff179687d27b522b9d3 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 20 Mar 2021 12:18:24 +0330 Subject: [PATCH 11/26] Add tests --- .../PatternParsingTests_ListPatterns.cs | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs index 208194a39504f..8ec9deaecb20a 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -612,5 +612,107 @@ public void SlicePattern_06() } 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.PropertyPatternClause); + { + 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.PropertyPatternClause); + { + 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(); + } } } From dd000b9b67be8688759b8675b218e75b3e3da9d9 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 20 Mar 2021 12:57:51 +0330 Subject: [PATCH 12/26] Suppress RS0027 --- src/Compilers/CSharp/Portable/GlobalSuppressions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs index 751f8d5a7383e..489f9f6aa0ca9 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")] From 12a5641ae44c9b3837bc675698f3156f009b15e6 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 20 Mar 2021 14:13:08 +0330 Subject: [PATCH 13/26] Fixup tests --- .../IOperationTests_IIsPatternExpression.cs | 11 +++++------ .../Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs | 3 +++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs index adbcb7164f06e..de07c27517a99 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs @@ -1090,18 +1090,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), @@ -1122,7 +1119,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..56498b408a252 100644 --- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs +++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs @@ -33,6 +33,9 @@ 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); var analyzer = new CSharpTrackingDiagnosticAnalyzer(); var options = new AnalyzerOptions(new[] { new TestAdditionalText() }.ToImmutableArray()); From 83e7f02b451573e23bf41bff63cd12b5e66d6868 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 20 Mar 2021 14:58:06 +0330 Subject: [PATCH 14/26] Add missing file header --- .../Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs index 8ec9deaecb20a..d87f082bb0482 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -1,4 +1,8 @@ -using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +// 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; From e5a67cf9b02cbd93a4bf95f2fae1aafa00d62fb2 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Sat, 20 Mar 2021 16:31:06 +0330 Subject: [PATCH 15/26] Fixup test --- .../DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs index a2a1db99543d7..5da6a53fecf4f 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs @@ -48,6 +48,9 @@ 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); var analyzer = new CSharpTrackingDiagnosticAnalyzer(); using var workspace = TestWorkspace.CreateCSharp(source, TestOptions.Regular, composition: s_compositionWithMockDiagnosticUpdateSourceRegistrationService); From 2cb368dc1ccc5c24c457891534a6a2daeaf5b8ce Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Tue, 23 Mar 2021 23:54:19 +0430 Subject: [PATCH 16/26] PR feedback --- .../Syntax.xml.Internal.Generated.cs | 26 ++++++++++++++----- .../Syntax.xml.Main.Generated.cs | 14 +++++++--- .../Syntax.xml.Syntax.Generated.cs | 8 ++---- .../Parser/LanguageParser_Patterns.cs | 5 ++-- .../CSharp/Portable/PublicAPI.Unshipped.txt | 3 ++- .../Syntax/PropertyPatternClauseSyntax.cs | 22 ++++++++++++++++ .../Portable/Syntax/RecursivePatternSyntax.cs | 2 +- .../CSharp/Portable/Syntax/Syntax.xml | 1 + .../CSharp/Portable/Syntax/SyntaxKind.cs | 1 + .../DiagnosticAnalyzerTests.AllInOne.cs | 1 + .../Generated/Syntax.Test.xml.Generated.cs | 4 +-- .../Syntax/Parsing/PatternParsingTests.cs | 2 +- .../PatternParsingTests_ListPatterns.cs | 14 +++++----- .../DiagnosticAnalyzerDriverTests.cs | 1 + 14 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs 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 a69557512cc4e..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 @@ -10967,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); @@ -36329,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)); @@ -36339,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); @@ -41241,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)); @@ -41251,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); 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 6e986f226add9..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 @@ -3605,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) 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 9dd2744fe328b..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 @@ -5082,11 +5082,6 @@ public RecursivePatternSyntax AddPositionalPatternClauseSubpatterns(params Subpa var positionalPatternClause = this.PositionalPatternClause ?? SyntaxFactory.PositionalPatternClause(); return WithPositionalPatternClause(positionalPatternClause.WithSubpatterns(positionalPatternClause.Subpatterns.AddRange(items))); } - public RecursivePatternSyntax AddPropertyPatternClauseSubpatterns(params SubpatternSyntax[] items) - { - var propertyPatternClause = this.PropertyPatternClause ?? SyntaxFactory.PropertyPatternClause(); - return WithPropertyPatternClause(propertyPatternClause.WithSubpatterns(propertyPatternClause.Subpatterns.AddRange(items))); - } } /// @@ -5192,6 +5187,7 @@ public PositionalPatternClauseSyntax Update(SyntaxToken openParenToken, Separate /// This node is associated with the following syntax kinds: /// /// + /// /// /// public sealed partial class PropertyPatternClauseSyntax : CSharpSyntaxNode @@ -5227,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; } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index ac9e3856140c3..f87b826b2ec9e 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -335,7 +335,7 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden } var positionalPatternClause = _syntaxFactory.PositionalPatternClause(openParenToken, subPatterns, closeParenToken); - var result = _syntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause: lengthPatternClause0, propertyPatternClause0, designation0); + var result = _syntaxFactory.RecursivePattern(type, positionalPatternClause, lengthPatternClause0, propertyPatternClause0, designation0); return result; } @@ -538,7 +538,8 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause() closeToken: out SyntaxToken closeBraceToken, openKind: SyntaxKind.OpenBraceToken, closeKind: SyntaxKind.CloseBraceToken); - return _syntaxFactory.PropertyPatternClause(openBraceToken, subPatterns, closeBraceToken); + var kind = subPatterns.Count > 0 && subPatterns[0].NameColon is null ? SyntaxKind.ListPatternClause : SyntaxKind.PropertyPatternClause; + return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken); } private void ParseSubpatternList( diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 24e8e4ee5be7e..f1adff15c0789 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.GetUsedAssemblyReferences(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Immutable.ImmutableArray -Microsoft.CodeAnalysis.CSharp.SyntaxKind.LengthPatternClause = 9035 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind Microsoft.CodeAnalysis.CSharp.SyntaxKind.SlicePattern = 9034 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.LengthPatternClause = 9035 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind +Microsoft.CodeAnalysis.CSharp.SyntaxKind.LengthPatternClause = 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..0e1ad211437bb --- /dev/null +++ b/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs @@ -0,0 +1,22 @@ +// 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) + { + return PropertyPatternClause(SyntaxKind.PropertyPatternClause, subpatterns); + } + } +} diff --git a/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs index 7a6319aa0b6e5..07305a2fd9c0d 100644 --- a/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs @@ -12,7 +12,7 @@ public partial class RecursivePatternSyntax { public RecursivePatternSyntax Update(TypeSyntax? type, PositionalPatternClauseSyntax? positionalPatternClause, PropertyPatternClauseSyntax? propertyPatternClause, VariableDesignationSyntax? designation) { - return Update(type, positionalPatternClause, lengthPatternClause: null, propertyPatternClause, designation); + return Update(type, positionalPatternClause, this.LengthPatternClause, propertyPatternClause, designation); } } } diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index dff818f5a8371..d2371ee50b256 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -2031,6 +2031,7 @@ + diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index f7d8163ad9868..2c67ce512632e 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -829,6 +829,7 @@ public enum SyntaxKind : ushort SlicePattern = 9034, LengthPatternClause = 9035, + ListPatternClause = 9036, // Kinds between 9000 and 9039 are "reserved" for pattern matching. diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs index 56498b408a252..94dd2ad7f717b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs +++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs @@ -36,6 +36,7 @@ public void DiagnosticAnalyzerAllInOne() // 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 1403f914aebc3..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 @@ -275,7 +275,7 @@ private static Syntax.InternalSyntax.PositionalPatternClauseSyntax GeneratePosit => 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()); @@ -10020,7 +10020,7 @@ 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()); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs index 55e631190e496..9d8d46b97a47c 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 index d87f082bb0482..7d97079e1dd89 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -386,7 +386,7 @@ void verify() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -431,7 +431,7 @@ void verify() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -463,7 +463,7 @@ public void SlicePattern_02() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -550,7 +550,7 @@ public void SlicePattern_05() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -589,7 +589,7 @@ public void SlicePattern_06() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -631,7 +631,7 @@ public void SlicePattern_07() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); @@ -680,7 +680,7 @@ public void SlicePattern_08() N(SyntaxKind.IsKeyword); N(SyntaxKind.RecursivePattern); { - N(SyntaxKind.PropertyPatternClause); + N(SyntaxKind.ListPatternClause); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.Subpattern); diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs index 5da6a53fecf4f..f471533681ae8 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs @@ -51,6 +51,7 @@ public async Task DiagnosticAnalyzerDriverAllInOne() // 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); From f9a3d49f411e91bd48194bcf45da565e5f1b64b8 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 06:50:00 +0430 Subject: [PATCH 17/26] PR feedback --- .../CSharp/Portable/Parser/LanguageParser.cs | 36 +- .../Parser/LanguageParser_Patterns.cs | 24 +- .../CSharp/Portable/PublicAPI.Unshipped.txt | 2 +- .../Syntax/PropertyPatternClauseSyntax.cs | 1 + .../CSharp/Portable/Syntax/SyntaxKind.cs | 1 + .../PatternParsingTests_ListPatterns.cs | 437 ++++++++++++++++++ 6 files changed, 464 insertions(+), 37 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 76e92195f7ac5..cf9c5d312639a 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6705,10 +6705,12 @@ bool canBeNullableType() continue; } goto done; // token not consumed - case SyntaxKind.OpenBracketToken when (nameOptions & NameOptions.PossiblePattern) != 0: - // We don't want to consume a sized rank specifier in patterns, we leave it out to parse it as a length pattern. + case SyntaxKind.OpenBracketToken: + // Now check for arrays. { - if (isOmittedSize()) + // 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()) { bool sawOpenBracket; var ranks = _pool.Allocate(); @@ -6718,7 +6720,7 @@ bool canBeNullableType() { ranks.Add(this.ParseArrayRankSpecifier(out _)); } - while ((sawOpenBracket = this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) && isOmittedSize()); + while ((sawOpenBracket = this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) && (!inPattern || isOmittedSize())); type = _syntaxFactory.ArrayType(type, ranks); } @@ -6731,29 +6733,7 @@ bool canBeNullableType() if (!sawOpenBracket) continue; } - goto done; - - bool isOmittedSize() => this.PeekToken(1).Kind is SyntaxKind.CommaToken or SyntaxKind.CloseBracketToken; - } - case SyntaxKind.OpenBracketToken: - // Now check for arrays. - { - var ranks = _pool.Allocate(); - try - { - do - { - ranks.Add(this.ParseArrayRankSpecifier(out _)); - } - while (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken); - - type = _syntaxFactory.ArrayType(type, ranks); - } - finally - { - _pool.Free(ranks); - } - continue; + goto done; // token not consumed } default: goto done; // token not consumed @@ -6763,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 f87b826b2ec9e..65cdd50740f33 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -210,7 +210,7 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b case SyntaxKind.DotDotToken: return _syntaxFactory.SlicePattern( CheckFeatureAvailability(EatToken(), MessageID.IDS_FeatureSlicePattern), - IsPossibleSubpatternElement() ? ParseNegatedPattern(precedence, afterIs: false, whenIsKeyword: false) : null); + IsPossibleSubpatternElement() ? ParseNegatedPattern(precedence, afterIs, whenIsKeyword) : null); case SyntaxKind.LessThanToken: case SyntaxKind.LessThanEqualsToken: case SyntaxKind.GreaterThanToken: @@ -305,7 +305,8 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden subPatterns: out SeparatedSyntaxList subPatterns, closeToken: out SyntaxToken closeParenToken, openKind: SyntaxKind.OpenParenToken, - closeKind: SyntaxKind.CloseParenToken); + closeKind: SyntaxKind.CloseParenToken, + isPropertyPattern: out _); parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause0); parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0); @@ -537,8 +538,9 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause() subPatterns: out SeparatedSyntaxList subPatterns, closeToken: out SyntaxToken closeBraceToken, openKind: SyntaxKind.OpenBraceToken, - closeKind: SyntaxKind.CloseBraceToken); - var kind = subPatterns.Count > 0 && subPatterns[0].NameColon is null ? SyntaxKind.ListPatternClause : SyntaxKind.PropertyPatternClause; + closeKind: SyntaxKind.CloseBraceToken, + out bool isPropertyPattern); + var kind = isPropertyPattern ? SyntaxKind.PropertyPatternClause : SyntaxKind.ListPatternClause; return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken); } @@ -547,8 +549,11 @@ private void ParseSubpatternList( out SeparatedSyntaxList subPatterns, out SyntaxToken closeToken, SyntaxKind openKind, - SyntaxKind closeKind) + SyntaxKind closeKind, + out bool isPropertyPattern) { + isPropertyPattern = true; + Debug.Assert((openKind, closeKind) is (SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken) or (SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)); @@ -559,11 +564,11 @@ private void ParseSubpatternList( try { tryAgain: - if (this.IsPossibleSubpatternElement() || this.CurrentToken.Kind == SyntaxKind.CommaToken) { + isPropertyPattern = false; // first pattern - list.Add(this.ParseSubpatternElement()); + list.Add(this.ParseSubpatternElement(ref isPropertyPattern)); // additional patterns int lastTokenPosition = -1; @@ -582,7 +587,7 @@ private void ParseSubpatternList( { break; } - list.Add(this.ParseSubpatternElement()); + list.Add(this.ParseSubpatternElement(ref isPropertyPattern)); continue; } else if (this.SkipBadPatternListTokens(ref openToken, list, SyntaxKind.CommaToken, closeKind) == PostSkipAction.Abort) @@ -605,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) @@ -613,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); diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index f1adff15c0789..78cdcc4bdbf1a 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1,4 +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.LengthPatternClause = 9036 -> 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 index 0e1ad211437bb..25aee5e166379 100644 --- a/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs @@ -14,6 +14,7 @@ public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken open { return PropertyPatternClause(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns, closeBraceToken); } + public static PropertyPatternClauseSyntax PropertyPatternClause(SeparatedSyntaxList subpatterns) { return PropertyPatternClause(SyntaxKind.PropertyPatternClause, subpatterns); diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index 2c67ce512632e..45829f23243cd 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -827,6 +827,7 @@ public enum SyntaxKind : ushort AndPattern = 9032, NotPattern = 9033, + // new patterns added in C# 10.0 SlicePattern = 9034, LengthPatternClause = 9035, ListPatternClause = 9036, diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs index 7d97079e1dd89..cc95d68ab4959 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -342,6 +342,303 @@ public void LengthPattern_08() } } + [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 NoRegressionOnEmptyPropertyPattern() { @@ -366,6 +663,38 @@ public void NoRegressionOnEmptyPropertyPattern() 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() { @@ -408,6 +737,59 @@ void verify() } } + [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() { @@ -718,5 +1100,60 @@ public void SlicePattern_08() } 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(); + } } } From 69301f5cd172280b36d1f4c744969b9f3e021ec1 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 06:58:30 +0430 Subject: [PATCH 18/26] Move --- .../Portable/Parser/LanguageParser_Patterns.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 65cdd50740f33..9a3ee31ed00fd 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -306,7 +306,7 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence preceden closeToken: out SyntaxToken closeParenToken, openKind: SyntaxKind.OpenParenToken, closeKind: SyntaxKind.CloseParenToken, - isPropertyPattern: out _); + isPropertyPatternClause: out _); parseLengthPatternClause(out LengthPatternClauseSyntax lengthPatternClause0); parsePropertyPatternClause(out PropertyPatternClauseSyntax propertyPatternClause0); @@ -539,8 +539,8 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause() closeToken: out SyntaxToken closeBraceToken, openKind: SyntaxKind.OpenBraceToken, closeKind: SyntaxKind.CloseBraceToken, - out bool isPropertyPattern); - var kind = isPropertyPattern ? SyntaxKind.PropertyPatternClause : SyntaxKind.ListPatternClause; + out bool isPropertyPatternClause); + var kind = isPropertyPatternClause ? SyntaxKind.PropertyPatternClause : SyntaxKind.ListPatternClause; return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken); } @@ -550,15 +550,15 @@ private void ParseSubpatternList( out SyntaxToken closeToken, SyntaxKind openKind, SyntaxKind closeKind, - out bool isPropertyPattern) + out bool isPropertyPatternClause) { - isPropertyPattern = true; - 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 @@ -566,9 +566,9 @@ private void ParseSubpatternList( tryAgain: if (this.IsPossibleSubpatternElement() || this.CurrentToken.Kind == SyntaxKind.CommaToken) { - isPropertyPattern = false; + isPropertyPatternClause = false; // first pattern - list.Add(this.ParseSubpatternElement(ref isPropertyPattern)); + list.Add(this.ParseSubpatternElement(ref isPropertyPatternClause)); // additional patterns int lastTokenPosition = -1; @@ -587,7 +587,7 @@ private void ParseSubpatternList( { break; } - list.Add(this.ParseSubpatternElement(ref isPropertyPattern)); + list.Add(this.ParseSubpatternElement(ref isPropertyPatternClause)); continue; } else if (this.SkipBadPatternListTokens(ref openToken, list, SyntaxKind.CommaToken, closeKind) == PostSkipAction.Abort) From e4759a3a774dcd0ae7befad6f42ac76147524100 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 07:44:42 +0430 Subject: [PATCH 19/26] Add missing member --- .../CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs | 2 +- .../CSharp/Portable/Syntax/RecursivePatternSyntax.cs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs index 25aee5e166379..4032b57704448 100644 --- a/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/PropertyPatternClauseSyntax.cs @@ -15,7 +15,7 @@ public static PropertyPatternClauseSyntax PropertyPatternClause(SyntaxToken open return PropertyPatternClause(SyntaxKind.PropertyPatternClause, openBraceToken, subpatterns, closeBraceToken); } - public static PropertyPatternClauseSyntax PropertyPatternClause(SeparatedSyntaxList subpatterns) + 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 index 07305a2fd9c0d..0138199debf84 100644 --- a/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/RecursivePatternSyntax.cs @@ -14,6 +14,12 @@ public RecursivePatternSyntax Update(TypeSyntax? type, PositionalPatternClauseSy { 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))); + } } } From 4668d89181ee2c3331695441528c05bc11a8a670 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 07:56:15 +0430 Subject: [PATCH 20/26] Fix test failures --- .../PropertySubPatternCompletionProvider.cs | 2 +- .../CSharp/Formatting/Rules/IndentBlockFormattingRule.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) 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/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); } From a39f0ee4f4dc0fe2be1ca8ddc9a4b54a82c297f1 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 07:56:31 +0430 Subject: [PATCH 21/26] Add PROTOTYPE comments --- .../CSharp/Portable/Compilation/CSharpSemanticModel.cs | 1 + .../Compiler/CSharp/Formatting/FormattingHelpers.cs | 2 ++ .../Compiler/CSharp/Formatting/Rules/BaseFormattingRule.cs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index d2f821e337c7b..fc30f3c5f58ce 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -4397,6 +4397,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/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 From 362f333f7ec13770c686c01a622f8070ae422440 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 08:21:54 +0430 Subject: [PATCH 22/26] The subpattern in a slice-pattern is no longer afterIs --- src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index 9a3ee31ed00fd..6f4ba91f68ac0 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -210,7 +210,7 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b case SyntaxKind.DotDotToken: return _syntaxFactory.SlicePattern( CheckFeatureAvailability(EatToken(), MessageID.IDS_FeatureSlicePattern), - IsPossibleSubpatternElement() ? ParseNegatedPattern(precedence, afterIs, whenIsKeyword) : null); + IsPossibleSubpatternElement() ? ParseNegatedPattern(precedence, afterIs: false, whenIsKeyword) : null); case SyntaxKind.LessThanToken: case SyntaxKind.LessThanEqualsToken: case SyntaxKind.GreaterThanToken: From 2a8e5b304d2d9ebfcd7a34d11669bb407f0a4edc Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 24 Mar 2021 10:27:50 +0430 Subject: [PATCH 23/26] Attempt to suppress RS0027 --- src/Compilers/CSharp/Portable/GlobalSuppressions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs index 489f9f6aa0ca9..dca5a2db834c5 100644 --- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs +++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs @@ -32,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")] From 19b73208128fabc06d9c50033826873cc1e13310 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Wed, 7 Apr 2021 20:06:12 +0430 Subject: [PATCH 24/26] Add more tests --- .../PatternParsingTests_ListPatterns.cs | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs index cc95d68ab4959..8b48a332ae5e5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -639,6 +639,40 @@ public void LengthPattern_15() 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() { @@ -1155,5 +1189,82 @@ public void SlicePattern_10() } 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(); + } } } From fe596e9fbfd207e7325d7a3d84ae8f0c1733f5a4 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Tue, 13 Apr 2021 20:33:34 +0430 Subject: [PATCH 25/26] Update resources --- .../CSharp/Portable/xlf/CSharpResources.cs.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.de.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.es.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.fr.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.it.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.ja.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.ko.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.pl.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.pt-BR.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.ru.xlf | 15 +++++++++++++++ .../CSharp/Portable/xlf/CSharpResources.tr.xlf | 15 +++++++++++++++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 15 +++++++++++++++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 15 +++++++++++++++ 13 files changed, 195 insertions(+) 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,此情形不受支援。 From f5b20c44c48bd0268d8e57b8e0df812e922504c9 Mon Sep 17 00:00:00 2001 From: Alireza Habibi Date: Tue, 13 Apr 2021 20:38:43 +0430 Subject: [PATCH 26/26] Add more tests --- .../PatternParsingTests_ListPatterns.cs | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs index 8b48a332ae5e5..024c9af699370 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests_ListPatterns.cs @@ -1266,5 +1266,256 @@ public void SlicePattern_12() } 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(); + } } }