From 93fdfeb405f6e6cba3ae7bea1f56a336a990542a Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Wed, 26 May 2021 17:39:41 -0700 Subject: [PATCH 1/6] Lambda expression explicit return type: parsing --- .../Portable/Generated/CSharp.Generated.g4 | 2 +- .../Syntax.xml.Internal.Generated.cs | 67 +- .../Syntax.xml.Main.Generated.cs | 12 +- .../Syntax.xml.Syntax.Generated.cs | 44 +- .../CSharp/Portable/Parser/LanguageParser.cs | 271 ++- .../ParenthesizedLambdaExpressionSyntax.cs | 8 +- .../CSharp/Portable/Syntax/Syntax.xml | 1 + .../Generated/Syntax.Test.xml.Generated.cs | 8 +- .../Parsing/LambdaReturnTypeParsingTests.cs | 1850 +++++++++++++++++ .../Parsing/LocalFunctionParsingTests.cs | 106 +- .../Test/Syntax/Parsing/ScriptParsingTests.cs | 43 +- 11 files changed, 2155 insertions(+), 257 deletions(-) create mode 100644 src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 index 17406ac149b7d..5578962ed4148 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 +++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 @@ -743,7 +743,7 @@ lambda_expression ; parenthesized_lambda_expression - : attribute_list* modifier* parameter_list '=>' (block | expression) + : attribute_list* modifier* type? parameter_list '=>' (block | expression) ; simple_lambda_expression 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 6bced1a20ae46..e3ca77f9e192b 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 @@ -6569,15 +6569,16 @@ internal sealed partial class ParenthesizedLambdaExpressionSyntax : LambdaExpres { internal readonly GreenNode? attributeLists; internal readonly GreenNode? modifiers; + internal readonly TypeSyntax? returnType; internal readonly ParameterListSyntax parameterList; internal readonly SyntaxToken arrowToken; internal readonly BlockSyntax? block; internal readonly ExpressionSyntax? expressionBody; - internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attributeLists, GreenNode? modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) + internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attributeLists, GreenNode? modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody, DiagnosticInfo[]? diagnostics, SyntaxAnnotation[]? annotations) : base(kind, diagnostics, annotations) { - this.SlotCount = 6; + this.SlotCount = 7; if (attributeLists != null) { this.AdjustFlagsAndWidth(attributeLists); @@ -6588,6 +6589,11 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu this.AdjustFlagsAndWidth(modifiers); this.modifiers = modifiers; } + if (returnType != null) + { + this.AdjustFlagsAndWidth(returnType); + this.returnType = returnType; + } this.AdjustFlagsAndWidth(parameterList); this.parameterList = parameterList; this.AdjustFlagsAndWidth(arrowToken); @@ -6604,11 +6610,11 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu } } - internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attributeLists, GreenNode? modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody, SyntaxFactoryContext context) + internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attributeLists, GreenNode? modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody, SyntaxFactoryContext context) : base(kind) { this.SetFactoryContext(context); - this.SlotCount = 6; + this.SlotCount = 7; if (attributeLists != null) { this.AdjustFlagsAndWidth(attributeLists); @@ -6619,6 +6625,11 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu this.AdjustFlagsAndWidth(modifiers); this.modifiers = modifiers; } + if (returnType != null) + { + this.AdjustFlagsAndWidth(returnType); + this.returnType = returnType; + } this.AdjustFlagsAndWidth(parameterList); this.parameterList = parameterList; this.AdjustFlagsAndWidth(arrowToken); @@ -6635,10 +6646,10 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu } } - internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attributeLists, GreenNode? modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) + internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attributeLists, GreenNode? modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) : base(kind) { - this.SlotCount = 6; + this.SlotCount = 7; if (attributeLists != null) { this.AdjustFlagsAndWidth(attributeLists); @@ -6649,6 +6660,11 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu this.AdjustFlagsAndWidth(modifiers); this.modifiers = modifiers; } + if (returnType != null) + { + this.AdjustFlagsAndWidth(returnType); + this.returnType = returnType; + } this.AdjustFlagsAndWidth(parameterList); this.parameterList = parameterList; this.AdjustFlagsAndWidth(arrowToken); @@ -6667,6 +6683,7 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu public override Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList AttributeLists => new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(this.attributeLists); public override Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList Modifiers => new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(this.modifiers); + public TypeSyntax? ReturnType => this.returnType; /// ParameterListSyntax node representing the list of parameters for the lambda expression. public ParameterListSyntax ParameterList => this.parameterList; /// SyntaxToken representing equals greater than. @@ -6687,10 +6704,11 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu { 0 => this.attributeLists, 1 => this.modifiers, - 2 => this.parameterList, - 3 => this.arrowToken, - 4 => this.block, - 5 => this.expressionBody, + 2 => this.returnType, + 3 => this.parameterList, + 4 => this.arrowToken, + 5 => this.block, + 6 => this.expressionBody, _ => null, }; @@ -6699,11 +6717,11 @@ internal ParenthesizedLambdaExpressionSyntax(SyntaxKind kind, GreenNode? attribu public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitParenthesizedLambdaExpression(this); public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitParenthesizedLambdaExpression(this); - public ParenthesizedLambdaExpressionSyntax Update(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax block, ExpressionSyntax expressionBody) + public ParenthesizedLambdaExpressionSyntax Update(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, TypeSyntax returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax block, ExpressionSyntax expressionBody) { - if (attributeLists != this.AttributeLists || modifiers != this.Modifiers || parameterList != this.ParameterList || arrowToken != this.ArrowToken || block != this.Block || expressionBody != this.ExpressionBody) + if (attributeLists != this.AttributeLists || modifiers != this.Modifiers || returnType != this.ReturnType || parameterList != this.ParameterList || arrowToken != this.ArrowToken || block != this.Block || expressionBody != this.ExpressionBody) { - var newNode = SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, parameterList, arrowToken, block, expressionBody); + var newNode = SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, returnType, parameterList, arrowToken, block, expressionBody); var diags = GetDiagnostics(); if (diags?.Length > 0) newNode = newNode.WithDiagnosticsGreen(diags); @@ -6717,15 +6735,15 @@ public ParenthesizedLambdaExpressionSyntax Update(Microsoft.CodeAnalysis.Syntax. } internal override GreenNode SetDiagnostics(DiagnosticInfo[]? diagnostics) - => new ParenthesizedLambdaExpressionSyntax(this.Kind, this.attributeLists, this.modifiers, this.parameterList, this.arrowToken, this.block, this.expressionBody, diagnostics, GetAnnotations()); + => new ParenthesizedLambdaExpressionSyntax(this.Kind, this.attributeLists, this.modifiers, this.returnType, this.parameterList, this.arrowToken, this.block, this.expressionBody, diagnostics, GetAnnotations()); internal override GreenNode SetAnnotations(SyntaxAnnotation[]? annotations) - => new ParenthesizedLambdaExpressionSyntax(this.Kind, this.attributeLists, this.modifiers, this.parameterList, this.arrowToken, this.block, this.expressionBody, GetDiagnostics(), annotations); + => new ParenthesizedLambdaExpressionSyntax(this.Kind, this.attributeLists, this.modifiers, this.returnType, this.parameterList, this.arrowToken, this.block, this.expressionBody, GetDiagnostics(), annotations); internal ParenthesizedLambdaExpressionSyntax(ObjectReader reader) : base(reader) { - this.SlotCount = 6; + this.SlotCount = 7; var attributeLists = (GreenNode?)reader.ReadValue(); if (attributeLists != null) { @@ -6738,6 +6756,12 @@ internal ParenthesizedLambdaExpressionSyntax(ObjectReader reader) AdjustFlagsAndWidth(modifiers); this.modifiers = modifiers; } + var returnType = (TypeSyntax?)reader.ReadValue(); + if (returnType != null) + { + AdjustFlagsAndWidth(returnType); + this.returnType = returnType; + } var parameterList = (ParameterListSyntax)reader.ReadValue(); AdjustFlagsAndWidth(parameterList); this.parameterList = parameterList; @@ -6763,6 +6787,7 @@ internal override void WriteTo(ObjectWriter writer) base.WriteTo(writer); writer.WriteValue(this.attributeLists); writer.WriteValue(this.modifiers); + writer.WriteValue(this.returnType); writer.WriteValue(this.parameterList); writer.WriteValue(this.arrowToken); writer.WriteValue(this.block); @@ -33691,7 +33716,7 @@ public override CSharpSyntaxNode VisitRefExpression(RefExpressionSyntax node) => node.Update((SyntaxToken)Visit(node.RefKeyword), (ExpressionSyntax)Visit(node.Expression)); public override CSharpSyntaxNode VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) - => node.Update(VisitList(node.AttributeLists), VisitList(node.Modifiers), (ParameterListSyntax)Visit(node.ParameterList), (SyntaxToken)Visit(node.ArrowToken), (BlockSyntax)Visit(node.Block), (ExpressionSyntax)Visit(node.ExpressionBody)); + => node.Update(VisitList(node.AttributeLists), VisitList(node.Modifiers), (TypeSyntax)Visit(node.ReturnType), (ParameterListSyntax)Visit(node.ParameterList), (SyntaxToken)Visit(node.ArrowToken), (BlockSyntax)Visit(node.Block), (ExpressionSyntax)Visit(node.ExpressionBody)); public override CSharpSyntaxNode VisitInitializerExpression(InitializerExpressionSyntax node) => node.Update((SyntaxToken)Visit(node.OpenBraceToken), VisitList(node.Expressions), (SyntaxToken)Visit(node.CloseBraceToken)); @@ -35499,7 +35524,7 @@ public RefExpressionSyntax RefExpression(SyntaxToken refKeyword, ExpressionSynta return result; } - public ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) + public ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) { #if DEBUG if (parameterList == null) throw new ArgumentNullException(nameof(parameterList)); @@ -35507,7 +35532,7 @@ public ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(Microso if (arrowToken.Kind != SyntaxKind.EqualsGreaterThanToken) throw new ArgumentException(nameof(arrowToken)); #endif - return new ParenthesizedLambdaExpressionSyntax(SyntaxKind.ParenthesizedLambdaExpression, attributeLists.Node, modifiers.Node, parameterList, arrowToken, block, expressionBody, this.context); + return new ParenthesizedLambdaExpressionSyntax(SyntaxKind.ParenthesizedLambdaExpression, attributeLists.Node, modifiers.Node, returnType, parameterList, arrowToken, block, expressionBody, this.context); } public InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList expressions, SyntaxToken closeBraceToken) @@ -40393,7 +40418,7 @@ public static RefExpressionSyntax RefExpression(SyntaxToken refKeyword, Expressi return result; } - public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) + public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList attributeLists, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) { #if DEBUG if (parameterList == null) throw new ArgumentNullException(nameof(parameterList)); @@ -40401,7 +40426,7 @@ public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression( if (arrowToken.Kind != SyntaxKind.EqualsGreaterThanToken) throw new ArgumentException(nameof(arrowToken)); #endif - return new ParenthesizedLambdaExpressionSyntax(SyntaxKind.ParenthesizedLambdaExpression, attributeLists.Node, modifiers.Node, parameterList, arrowToken, block, expressionBody); + return new ParenthesizedLambdaExpressionSyntax(SyntaxKind.ParenthesizedLambdaExpression, attributeLists.Node, modifiers.Node, returnType, parameterList, arrowToken, block, expressionBody); } public static InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, SyntaxToken openBraceToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList expressions, SyntaxToken closeBraceToken) 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 66690ae17168a..4fef29ab544a6 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 @@ -1570,7 +1570,7 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor => node.Update(VisitToken(node.RefKeyword), (ExpressionSyntax?)Visit(node.Expression) ?? throw new ArgumentNullException("expression")); public override SyntaxNode? VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpressionSyntax node) - => node.Update(VisitList(node.AttributeLists), VisitList(node.Modifiers), (ParameterListSyntax?)Visit(node.ParameterList) ?? throw new ArgumentNullException("parameterList"), VisitToken(node.ArrowToken), (BlockSyntax?)Visit(node.Block), (ExpressionSyntax?)Visit(node.ExpressionBody)); + => node.Update(VisitList(node.AttributeLists), VisitList(node.Modifiers), (TypeSyntax?)Visit(node.ReturnType), (ParameterListSyntax?)Visit(node.ParameterList) ?? throw new ArgumentNullException("parameterList"), VisitToken(node.ArrowToken), (BlockSyntax?)Visit(node.Block), (ExpressionSyntax?)Visit(node.ExpressionBody)); public override SyntaxNode? VisitInitializerExpression(InitializerExpressionSyntax node) => node.Update(VisitToken(node.OpenBraceToken), VisitList(node.Expressions), VisitToken(node.CloseBraceToken)); @@ -3083,20 +3083,20 @@ public static RefExpressionSyntax RefExpression(ExpressionSyntax expression) => SyntaxFactory.RefExpression(SyntaxFactory.Token(SyntaxKind.RefKeyword), expression); /// Creates a new ParenthesizedLambdaExpressionSyntax instance. - public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxList attributeLists, SyntaxTokenList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) + public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxList attributeLists, SyntaxTokenList modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) { if (parameterList == null) throw new ArgumentNullException(nameof(parameterList)); if (arrowToken.Kind() != SyntaxKind.EqualsGreaterThanToken) throw new ArgumentException(nameof(arrowToken)); - return (ParenthesizedLambdaExpressionSyntax)Syntax.InternalSyntax.SyntaxFactory.ParenthesizedLambdaExpression(attributeLists.Node.ToGreenList(), modifiers.Node.ToGreenList(), (Syntax.InternalSyntax.ParameterListSyntax)parameterList.Green, (Syntax.InternalSyntax.SyntaxToken)arrowToken.Node!, block == null ? null : (Syntax.InternalSyntax.BlockSyntax)block.Green, expressionBody == null ? null : (Syntax.InternalSyntax.ExpressionSyntax)expressionBody.Green).CreateRed(); + return (ParenthesizedLambdaExpressionSyntax)Syntax.InternalSyntax.SyntaxFactory.ParenthesizedLambdaExpression(attributeLists.Node.ToGreenList(), modifiers.Node.ToGreenList(), returnType == null ? null : (Syntax.InternalSyntax.TypeSyntax)returnType.Green, (Syntax.InternalSyntax.ParameterListSyntax)parameterList.Green, (Syntax.InternalSyntax.SyntaxToken)arrowToken.Node!, block == null ? null : (Syntax.InternalSyntax.BlockSyntax)block.Green, expressionBody == null ? null : (Syntax.InternalSyntax.ExpressionSyntax)expressionBody.Green).CreateRed(); } /// Creates a new ParenthesizedLambdaExpressionSyntax instance. - public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxList attributeLists, SyntaxTokenList modifiers, ParameterListSyntax parameterList, BlockSyntax? block, ExpressionSyntax? expressionBody) - => SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, parameterList, SyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), block, expressionBody); + public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxList attributeLists, SyntaxTokenList modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, BlockSyntax? block, ExpressionSyntax? expressionBody) + => SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, returnType, parameterList, SyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), block, expressionBody); /// Creates a new ParenthesizedLambdaExpressionSyntax instance. public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression() - => SyntaxFactory.ParenthesizedLambdaExpression(default, default(SyntaxTokenList), SyntaxFactory.ParameterList(), SyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), default, default); + => SyntaxFactory.ParenthesizedLambdaExpression(default, default(SyntaxTokenList), default, SyntaxFactory.ParameterList(), SyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), default, default); /// Creates a new InitializerExpressionSyntax instance. public static InitializerExpressionSyntax InitializerExpression(SyntaxKind kind, SyntaxToken openBraceToken, SeparatedSyntaxList expressions, SyntaxToken closeBraceToken) 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 e5528217336a2..eb1d16d6efa74 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 @@ -3210,6 +3210,7 @@ public RefExpressionSyntax Update(SyntaxToken refKeyword, ExpressionSyntax expre public sealed partial class ParenthesizedLambdaExpressionSyntax : LambdaExpressionSyntax { private SyntaxNode? attributeLists; + private TypeSyntax? returnType; private ParameterListSyntax? parameterList; private BlockSyntax? block; private ExpressionSyntax? expressionBody; @@ -3230,31 +3231,34 @@ public override SyntaxTokenList Modifiers } } + public TypeSyntax? ReturnType => GetRed(ref this.returnType, 2); + /// ParameterListSyntax node representing the list of parameters for the lambda expression. - public ParameterListSyntax ParameterList => GetRed(ref this.parameterList, 2)!; + public ParameterListSyntax ParameterList => GetRed(ref this.parameterList, 3)!; /// SyntaxToken representing equals greater than. - public override SyntaxToken ArrowToken => new SyntaxToken(this, ((Syntax.InternalSyntax.ParenthesizedLambdaExpressionSyntax)this.Green).arrowToken, GetChildPosition(3), GetChildIndex(3)); + public override SyntaxToken ArrowToken => new SyntaxToken(this, ((Syntax.InternalSyntax.ParenthesizedLambdaExpressionSyntax)this.Green).arrowToken, GetChildPosition(4), GetChildIndex(4)); /// /// BlockSyntax node representing the body of the lambda. /// Only one of Block or ExpressionBody will be non-null. /// - public override BlockSyntax? Block => GetRed(ref this.block, 4); + public override BlockSyntax? Block => GetRed(ref this.block, 5); /// /// ExpressionSyntax node representing the body of the lambda. /// Only one of Block or ExpressionBody will be non-null. /// - public override ExpressionSyntax? ExpressionBody => GetRed(ref this.expressionBody, 5); + public override ExpressionSyntax? ExpressionBody => GetRed(ref this.expressionBody, 6); internal override SyntaxNode? GetNodeSlot(int index) => index switch { 0 => GetRedAtZero(ref this.attributeLists)!, - 2 => GetRed(ref this.parameterList, 2)!, - 4 => GetRed(ref this.block, 4), - 5 => GetRed(ref this.expressionBody, 5), + 2 => GetRed(ref this.returnType, 2), + 3 => GetRed(ref this.parameterList, 3)!, + 5 => GetRed(ref this.block, 5), + 6 => GetRed(ref this.expressionBody, 6), _ => null, }; @@ -3262,20 +3266,21 @@ public override SyntaxTokenList Modifiers => index switch { 0 => this.attributeLists, - 2 => this.parameterList, - 4 => this.block, - 5 => this.expressionBody, + 2 => this.returnType, + 3 => this.parameterList, + 5 => this.block, + 6 => this.expressionBody, _ => null, }; public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitParenthesizedLambdaExpression(this); public override TResult? Accept(CSharpSyntaxVisitor visitor) where TResult : default => visitor.VisitParenthesizedLambdaExpression(this); - public ParenthesizedLambdaExpressionSyntax Update(SyntaxList attributeLists, SyntaxTokenList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) + public ParenthesizedLambdaExpressionSyntax Update(SyntaxList attributeLists, SyntaxTokenList modifiers, TypeSyntax? returnType, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) { - if (attributeLists != this.AttributeLists || modifiers != this.Modifiers || parameterList != this.ParameterList || arrowToken != this.ArrowToken || block != this.Block || expressionBody != this.ExpressionBody) + if (attributeLists != this.AttributeLists || modifiers != this.Modifiers || returnType != this.ReturnType || parameterList != this.ParameterList || arrowToken != this.ArrowToken || block != this.Block || expressionBody != this.ExpressionBody) { - var newNode = SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, parameterList, arrowToken, block, expressionBody); + var newNode = SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, returnType, parameterList, arrowToken, block, expressionBody); var annotations = GetAnnotations(); return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode; } @@ -3284,16 +3289,17 @@ public ParenthesizedLambdaExpressionSyntax Update(SyntaxList attributeLists) => WithAttributeLists(attributeLists); - public new ParenthesizedLambdaExpressionSyntax WithAttributeLists(SyntaxList attributeLists) => Update(attributeLists, this.Modifiers, this.ParameterList, this.ArrowToken, this.Block, this.ExpressionBody); + public new ParenthesizedLambdaExpressionSyntax WithAttributeLists(SyntaxList attributeLists) => Update(attributeLists, this.Modifiers, this.ReturnType, this.ParameterList, this.ArrowToken, this.Block, this.ExpressionBody); internal override AnonymousFunctionExpressionSyntax WithModifiersCore(SyntaxTokenList modifiers) => WithModifiers(modifiers); - public new ParenthesizedLambdaExpressionSyntax WithModifiers(SyntaxTokenList modifiers) => Update(this.AttributeLists, modifiers, this.ParameterList, this.ArrowToken, this.Block, this.ExpressionBody); - public ParenthesizedLambdaExpressionSyntax WithParameterList(ParameterListSyntax parameterList) => Update(this.AttributeLists, this.Modifiers, parameterList, this.ArrowToken, this.Block, this.ExpressionBody); + public new ParenthesizedLambdaExpressionSyntax WithModifiers(SyntaxTokenList modifiers) => Update(this.AttributeLists, modifiers, this.ReturnType, this.ParameterList, this.ArrowToken, this.Block, this.ExpressionBody); + public ParenthesizedLambdaExpressionSyntax WithReturnType(TypeSyntax? returnType) => Update(this.AttributeLists, this.Modifiers, returnType, this.ParameterList, this.ArrowToken, this.Block, this.ExpressionBody); + public ParenthesizedLambdaExpressionSyntax WithParameterList(ParameterListSyntax parameterList) => Update(this.AttributeLists, this.Modifiers, this.ReturnType, parameterList, this.ArrowToken, this.Block, this.ExpressionBody); internal override LambdaExpressionSyntax WithArrowTokenCore(SyntaxToken arrowToken) => WithArrowToken(arrowToken); - public new ParenthesizedLambdaExpressionSyntax WithArrowToken(SyntaxToken arrowToken) => Update(this.AttributeLists, this.Modifiers, this.ParameterList, arrowToken, this.Block, this.ExpressionBody); + public new ParenthesizedLambdaExpressionSyntax WithArrowToken(SyntaxToken arrowToken) => Update(this.AttributeLists, this.Modifiers, this.ReturnType, this.ParameterList, arrowToken, this.Block, this.ExpressionBody); internal override AnonymousFunctionExpressionSyntax WithBlockCore(BlockSyntax? block) => WithBlock(block); - public new ParenthesizedLambdaExpressionSyntax WithBlock(BlockSyntax? block) => Update(this.AttributeLists, this.Modifiers, this.ParameterList, this.ArrowToken, block, this.ExpressionBody); + public new ParenthesizedLambdaExpressionSyntax WithBlock(BlockSyntax? block) => Update(this.AttributeLists, this.Modifiers, this.ReturnType, this.ParameterList, this.ArrowToken, block, this.ExpressionBody); internal override AnonymousFunctionExpressionSyntax WithExpressionBodyCore(ExpressionSyntax? expressionBody) => WithExpressionBody(expressionBody); - public new ParenthesizedLambdaExpressionSyntax WithExpressionBody(ExpressionSyntax? expressionBody) => Update(this.AttributeLists, this.Modifiers, this.ParameterList, this.ArrowToken, this.Block, expressionBody); + public new ParenthesizedLambdaExpressionSyntax WithExpressionBody(ExpressionSyntax? expressionBody) => Update(this.AttributeLists, this.Modifiers, this.ReturnType, this.ParameterList, this.ArrowToken, this.Block, expressionBody); internal override LambdaExpressionSyntax AddAttributeListsCore(params AttributeListSyntax[] items) => AddAttributeLists(items); public new ParenthesizedLambdaExpressionSyntax AddAttributeLists(params AttributeListSyntax[] items) => WithAttributeLists(this.AttributeLists.AddRange(items)); diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 88bc472607d29..9eb616dae5693 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -9726,6 +9726,7 @@ private bool IsPossibleExpression() return IsPossibleExpression(allowBinaryExpressions: true, allowAssignmentExpressions: true); } + // PROTOTYPE: Does this need to be updated to include lambdas with explicit return type? private bool IsPossibleExpression(bool allowBinaryExpressions, bool allowAssignmentExpressions) { SyntaxKind tk = this.CurrentToken.Kind; @@ -9826,7 +9827,7 @@ internal static bool IsRightAssociative(SyntaxKind op) } } - enum Precedence : uint + private enum Precedence : uint { Expression = 0, // Loosest possible precedence, used to accept all expressions Assignment = Expression, @@ -10468,14 +10469,27 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) case SyntaxKind.StackAllocKeyword: return this.ParseStackAllocExpression(); case SyntaxKind.DelegateKeyword: + if (this.IsPossibleLambdaExpression(precedence)) + { + return this.ParseLambdaExpression(); + } return this.ParseAnonymousMethodExpression(); case SyntaxKind.RefKeyword: + if (this.IsPossibleLambdaExpression(precedence)) + { + return this.ParseLambdaExpression(); + } // ref is not expected to appear in this position. return this.AddError(ParsePossibleRefExpression(), ErrorCode.ERR_InvalidExprTerm, SyntaxFacts.GetText(tk)); default: // check for intrinsic type followed by '.' if (IsPredefinedType(tk)) { + if (this.IsPossibleLambdaExpression(precedence)) + { + return this.ParseLambdaExpression(); + } + var expr = _syntaxFactory.PredefinedType(this.EatToken()); if (this.CurrentToken.Kind != SyntaxKind.DotToken || tk == SyntaxKind.VoidKeyword) @@ -11205,11 +11219,6 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) return foundParameterModifier; case SyntaxKind.CommaToken: - if (foundParameterModifier) - { - return true; - } - continue; case SyntaxKind.CloseParenToken: @@ -11231,14 +11240,14 @@ private ExpressionSyntax ParseCastOrParenExpressionOrLambdaOrTuple(Precedence pr { Debug.Assert(this.CurrentToken.Kind == SyntaxKind.OpenParenToken); + if (IsPossibleLambdaExpression(precedence)) + { + return this.ParseLambdaExpression(); + } + var resetPoint = this.GetResetPoint(); try { - if (ScanParenthesizedImplicitlyTypedLambda(precedence)) - { - return this.ParseLambdaExpression(); - } - // We have a decision to make -- is this a cast, or is it a parenthesized // expression? Because look-ahead is cheap with our token stream, we check // to see if this "looks like" a cast (without constructing any parse trees) @@ -11440,160 +11449,126 @@ bool isBinaryPatternKeyword() } } + /// + /// Tokens that match the following are considered a possible lambda expression: + /// attribute-list* ('async' | 'static')* type? ('(' | identifier) ... + /// For better error recovery 'static =>' is also considered a possible lambda expression. + /// private bool IsPossibleLambdaExpression(Precedence precedence) { - // Only call into this if after `static`, '[', or after a legal identifier. - Debug.Assert( - this.CurrentToken.Kind is SyntaxKind.StaticKeyword or SyntaxKind.OpenBracketToken || - this.IsTrueIdentifier(this.CurrentToken)); if (precedence > Precedence.Lambda) { return false; } - if (this.CurrentToken.Kind == SyntaxKind.OpenBracketToken) + var resetPoint = this.GetResetPoint(); + try { - var resetPoint = this.GetResetPoint(); - try + if (CurrentToken.Kind == SyntaxKind.OpenBracketToken) { _ = ParseAttributeDeclarations(); - return CurrentToken.Kind switch - { - SyntaxKind.StaticKeyword or SyntaxKind.IdentifierToken => IsPossibleLambdaExpressionCore(precedence), - SyntaxKind.OpenParenToken => ScanParenthesizedLambda(precedence), - _ => false, - }; } - finally + + bool seenStatic; + if (this.CurrentToken.Kind == SyntaxKind.StaticKeyword) { - this.Reset(ref resetPoint); - this.Release(ref resetPoint); + EatToken(); + seenStatic = true; + } + else if (this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword && + this.PeekToken(1).Kind == SyntaxKind.StaticKeyword) + { + EatToken(); + EatToken(); + seenStatic = true; + } + else + { + seenStatic = false; } - } - else - { - return IsPossibleLambdaExpressionCore(precedence); - } - } - - private bool IsPossibleLambdaExpressionCore(Precedence precedence) - { - // Only call into this if after `static` or after a legal identifier. - Debug.Assert( - this.CurrentToken.Kind == SyntaxKind.StaticKeyword || - this.IsTrueIdentifier(this.CurrentToken)); - Debug.Assert(precedence <= Precedence.Lambda); - - // If we start with `static` or `async static` then just jump past those and do the - // analysis after that point. Note, we don't just blindly consume `async` in `static - // async` because that `async` may not be a modifier (it may just be an identifier) and - // we have to figure out what it is. - - int peekIndex; - bool seenStatic; - if (this.CurrentToken.Kind == SyntaxKind.StaticKeyword) - { - peekIndex = 1; - seenStatic = true; - } - else if (this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword && - this.PeekToken(1).Kind == SyntaxKind.StaticKeyword) - { - peekIndex = 2; - seenStatic = true; - } - else - { - peekIndex = 0; - seenStatic = false; - } - if (this.PeekToken(peekIndex).Kind == SyntaxKind.EqualsGreaterThanToken) - { - // We only got into IsPossibleLambdaExpression if we saw 'static' or an identifier. - // So if we're now on => then we must have been on 'static' in order to have moved - // past those. - Contract.Requires(seenStatic); + if (seenStatic) + { + if (this.CurrentToken.Kind == SyntaxKind.EqualsGreaterThanToken) + { + // 1. `static =>` + // 2. `async static =>` - // 1. `static =>` - // 2. `async static =>` + // This is an error case, but we have enough code in front of us to be certain + // the user was trying to write a static lambda. + return true; + } - // This is an error case, but we have enough code in front of us to be certain - // the user was trying to write a static lambda. - return true; - } + if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) + { + // 1. `static (... + // 2. `async static (... + return true; + } + } - if (this.PeekToken(peekIndex).Kind == SyntaxKind.IdentifierToken && - this.PeekToken(peekIndex + 1).Kind == SyntaxKind.EqualsGreaterThanToken) - { - // 1. `a => ...` - // 1. `static a => ...` - // 2. `async static a => ...` - return true; - } + if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && + this.PeekToken(1).Kind == SyntaxKind.EqualsGreaterThanToken) + { + // 1. `a => ...` + // 1. `static a => ...` + // 2. `async static a => ...` + return true; + } - if (this.PeekToken(peekIndex).Kind == SyntaxKind.OpenParenToken) - { - // We only got into IsPossibleLambdaExpression if we saw 'static' or an identifier. - // So if we're now on ( then we must have been on 'static' in order to have moved - // past those. - Contract.Requires(seenStatic); + // Have checked all the static forms. And have checked for the basic `a => a` form. + // At this point we have must be on 'async' or an explicit return type for this to still be a lambda. + if (this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword) + { + EatToken(); + } - // 1. `static (... - // 2. `async static (... - return true; - } + var nestedResetPoint = this.GetResetPoint(); + try + { + var st = ScanType(); // PROTOTYPE: Are default arguments to ScanType() correct? + if (st == ScanTypeFlags.NotType || this.CurrentToken.Kind != SyntaxKind.OpenParenToken) + { + this.Reset(ref nestedResetPoint); + } + } + finally + { + this.Release(ref nestedResetPoint); + } - // Have checked all the static forms. And have checked for the basic `a => a` form. - // At this point we have must be on 'async' for this to still be a lambda. - if (this.PeekToken(peekIndex).ContextualKind != SyntaxKind.AsyncKeyword) - { - return false; - } + // However, just because we're on `async` doesn't mean we're a lambda. We might have + // something lambda-like like: + // + // async a => ... // or + // async (a) => ... + // + // Or we could have something that isn't a lambda like: + // + // async (); - peekIndex++; - // However, just because we're on `async` doesn't mean we're a lambda. We might have - // something lambda-like like: - // - // async a => ... // or - // async (a) => ... - // - // Or we could have something that isn't a lambda like: - // - // async (); + // 'async => ...' looks like an async simple lambda + if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && + this.PeekToken(1).Kind == SyntaxKind.EqualsGreaterThanToken) + { + // async a => ... + return true; + } - // 'async => ...' looks like an async simple lambda - if (this.PeekToken(peekIndex).Kind == SyntaxKind.IdentifierToken && - this.PeekToken(peekIndex + 1).Kind == SyntaxKind.EqualsGreaterThanToken) - { - // async a => ... - return true; - } + // Non-simple async lambda must be of the form 'async (...' + if (this.CurrentToken.Kind != SyntaxKind.OpenParenToken) + { + return false; + } - // Non-simple async lambda must be of the form 'async (...' - if (this.PeekToken(peekIndex).Kind != SyntaxKind.OpenParenToken) - { - return false; + // Check whether looks like implicitly or explicitly typed lambda + return ScanParenthesizedLambda(precedence); } - - // we have `async (`. Could be a lambda, or could be an invocation of something called - // `async`. Have to do a more costly speculative scan to find out. - var resetPoint = this.GetResetPoint(); - - // Skip all tokens until we go past 'async' - for (int i = 0; i < peekIndex; i++) + finally { - EatToken(); + this.Reset(ref resetPoint); + this.Release(ref resetPoint); } - - // Check whether looks like implicitly or explicitly typed lambda - bool isAsync = ScanParenthesizedLambda(precedence); - - // Restore current token index - this.Reset(ref resetPoint); - this.Release(ref resetPoint); - - return isAsync; } private static bool CanFollowCast(SyntaxKind kind) @@ -12420,6 +12395,22 @@ LambdaExpressionSyntax parseLambdaExpressionWorker() this.IsInAsync = true; } + TypeSyntax returnType; + var resetPoint = this.GetResetPoint(); + try + { + returnType = ParseReturnType(); + if (CurrentToken.Kind != SyntaxKind.OpenParenToken) + { + this.Reset(ref resetPoint); + returnType = null; + } + } + finally + { + this.Release(ref resetPoint); + } + if (this.CurrentToken.Kind == SyntaxKind.OpenParenToken) { var paramList = this.ParseLambdaParameterList(); @@ -12428,7 +12419,7 @@ LambdaExpressionSyntax parseLambdaExpressionWorker() var (block, expression) = ParseLambdaBody(); return _syntaxFactory.ParenthesizedLambdaExpression( - attributes, modifiers, paramList, arrow, block, expression); + attributes, modifiers, returnType, paramList, arrow, block, expression); } else { diff --git a/src/Compilers/CSharp/Portable/Syntax/ParenthesizedLambdaExpressionSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/ParenthesizedLambdaExpressionSyntax.cs index 64a454143eb49..cd754fc6bf5de 100644 --- a/src/Compilers/CSharp/Portable/Syntax/ParenthesizedLambdaExpressionSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/ParenthesizedLambdaExpressionSyntax.cs @@ -32,6 +32,9 @@ public ParenthesizedLambdaExpressionSyntax Update(SyntaxToken asyncKeyword, Para public ParenthesizedLambdaExpressionSyntax Update(SyntaxTokenList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) => Update(this.AttributeLists, modifiers, parameterList, arrowToken, block, expressionBody); + + public ParenthesizedLambdaExpressionSyntax Update(SyntaxList attributeLists, SyntaxTokenList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) + => Update(attributeLists, modifiers, returnType: null, parameterList, arrowToken, block, expressionBody); } } @@ -46,9 +49,12 @@ public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression( => ParenthesizedLambdaExpression(default(SyntaxTokenList), parameterList, block, expressionBody); public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxTokenList modifiers, ParameterListSyntax parameterList, SyntaxToken arrowToken, BlockSyntax? block, ExpressionSyntax? expressionBody) - => SyntaxFactory.ParenthesizedLambdaExpression(attributeLists: default, modifiers, parameterList, arrowToken, block, expressionBody); + => SyntaxFactory.ParenthesizedLambdaExpression(attributeLists: default, modifiers, returnType: null, parameterList, arrowToken, block, expressionBody); public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxTokenList modifiers, ParameterListSyntax parameterList, BlockSyntax? block, ExpressionSyntax? expressionBody) => SyntaxFactory.ParenthesizedLambdaExpression(attributeLists: default, modifiers, parameterList, block, expressionBody); + + public static ParenthesizedLambdaExpressionSyntax ParenthesizedLambdaExpression(SyntaxList attributeLists, SyntaxTokenList modifiers, ParameterListSyntax parameterList, BlockSyntax? block, ExpressionSyntax? expressionBody) + => SyntaxFactory.ParenthesizedLambdaExpression(attributeLists, modifiers, returnType: null, parameterList, block, expressionBody); } } diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 92ce9b7773454..339d62049b787 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1448,6 +1448,7 @@ + ParameterListSyntax node representing the list of parameters for the lambda expression. 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 6180e30fec559..8fa6b4863cefe 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 @@ -173,7 +173,7 @@ private static Syntax.InternalSyntax.RefExpressionSyntax GenerateRefExpression() => InternalSyntaxFactory.RefExpression(InternalSyntaxFactory.Token(SyntaxKind.RefKeyword), GenerateIdentifierName()); private static Syntax.InternalSyntax.ParenthesizedLambdaExpressionSyntax GenerateParenthesizedLambdaExpression() - => InternalSyntaxFactory.ParenthesizedLambdaExpression(new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), GenerateParameterList(), InternalSyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), null, null); + => InternalSyntaxFactory.ParenthesizedLambdaExpression(new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), null, GenerateParameterList(), InternalSyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), null, null); private static Syntax.InternalSyntax.InitializerExpressionSyntax GenerateInitializerExpression() => InternalSyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, InternalSyntaxFactory.Token(SyntaxKind.OpenBraceToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.CloseBraceToken)); @@ -1345,6 +1345,7 @@ public void TestParenthesizedLambdaExpressionFactoryAndProperties() Assert.Equal(default, node.AttributeLists); Assert.Equal(default, node.Modifiers); + Assert.Null(node.ReturnType); Assert.NotNull(node.ParameterList); Assert.Equal(SyntaxKind.EqualsGreaterThanToken, node.ArrowToken.Kind); Assert.Null(node.Block); @@ -9840,7 +9841,7 @@ private static RefExpressionSyntax GenerateRefExpression() => SyntaxFactory.RefExpression(SyntaxFactory.Token(SyntaxKind.RefKeyword), GenerateIdentifierName()); private static ParenthesizedLambdaExpressionSyntax GenerateParenthesizedLambdaExpression() - => SyntaxFactory.ParenthesizedLambdaExpression(new SyntaxList(), new SyntaxTokenList(), GenerateParameterList(), SyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), default(BlockSyntax), default(ExpressionSyntax)); + => SyntaxFactory.ParenthesizedLambdaExpression(new SyntaxList(), new SyntaxTokenList(), default(TypeSyntax), GenerateParameterList(), SyntaxFactory.Token(SyntaxKind.EqualsGreaterThanToken), default(BlockSyntax), default(ExpressionSyntax)); private static InitializerExpressionSyntax GenerateInitializerExpression() => SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, SyntaxFactory.Token(SyntaxKind.OpenBraceToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.CloseBraceToken)); @@ -11012,11 +11013,12 @@ public void TestParenthesizedLambdaExpressionFactoryAndProperties() Assert.Equal(default, node.AttributeLists); Assert.Equal(default, node.Modifiers); + Assert.Null(node.ReturnType); Assert.NotNull(node.ParameterList); Assert.Equal(SyntaxKind.EqualsGreaterThanToken, node.ArrowToken.Kind()); Assert.Null(node.Block); Assert.Null(node.ExpressionBody); - var newNode = node.WithAttributeLists(node.AttributeLists).WithModifiers(node.Modifiers).WithParameterList(node.ParameterList).WithArrowToken(node.ArrowToken).WithBlock(node.Block).WithExpressionBody(node.ExpressionBody); + var newNode = node.WithAttributeLists(node.AttributeLists).WithModifiers(node.Modifiers).WithReturnType(node.ReturnType).WithParameterList(node.ParameterList).WithArrowToken(node.ArrowToken).WithBlock(node.Block).WithExpressionBody(node.ExpressionBody); Assert.Equal(node, newNode); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs new file mode 100644 index 0000000000000..31c413cb11880 --- /dev/null +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs @@ -0,0 +1,1850 @@ +// 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 Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class LambdaReturnTypeParsingTests : ParsingTests + { + public LambdaReturnTypeParsingTests(ITestOutputHelper output) : base(output) { } + + protected override SyntaxTree ParseTree(string text, CSharpParseOptions? options) + { + return SyntaxFactory.ParseSyntaxTree(text, options: options); + } + + protected override CSharpSyntaxNode ParseNode(string text, CSharpParseOptions? options) + { + return SyntaxFactory.ParseExpression(text, options: options); + } + + [Fact] + public void ExplicitReturnType_01() + { + string source = "T () => default"; + UsingExpression(source, TestOptions.Regular9); + verify(); + + UsingExpression(source, TestOptions.RegularPreview); + verify(); + + void verify() + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + } + + [Fact] + public void ExplicitReturnType_02() + { + string source = "T (x) => { return x; }"; + UsingExpression(source, TestOptions.Regular9); + verify(); + + UsingExpression(source, TestOptions.RegularPreview); + verify(); + + void verify() + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.ReturnStatement); + { + N(SyntaxKind.ReturnKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + } + + [Fact] + public void ExplicitReturnType_03() + { + string source = "T (T x) => x"; + UsingExpression(source, TestOptions.Regular9); + verify(); + + UsingExpression(source, TestOptions.RegularPreview); + verify(); + + void verify() + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + } + + [Fact] + public void ExplicitReturnType_04() + { + string source = "T x => y"; + UsingExpression(source, TestOptions.Regular9, + // (1,1): error CS1073: Unexpected token 'x' + // T x => y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "T").WithArguments("x").WithLocation(1, 1)); + verify(); + + UsingExpression(source, TestOptions.RegularPreview, + // (1,1): error CS1073: Unexpected token 'x' + // T x => y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "T").WithArguments("x").WithLocation(1, 1)); + verify(); + + void verify() + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + EOF(); + } + } + + [Fact] + public void ExplicitReturnType_05() + { + string source = "int (_) => 0"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "_"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_06() + { + string source = "void () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_07() + { + string source = "T[] () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_08() + { + string source = "T* () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_09() + { + string source = "delegate* () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_10() + { + string source = "T? () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_11() + { + string source = "int? () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_12() + { + string source = "A.B () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_13() + { + string source = "A::B () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AliasQualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ColonColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_14() + { + string source = "global::T () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AliasQualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.GlobalKeyword); + } + N(SyntaxKind.ColonColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_15() + { + string source = "A () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_16() + { + string source = "A.C () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_17() + { + string source = "(int, object) () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_18() + { + string source = "(int x, object y) () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.IdentifierToken, "y"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_19() + { + string source = "var (x, y) => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "y"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_20() + { + string source = "int (x, y) => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "y"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_21() + { + string source = "A () => () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_22() + { + string source = "A () => B () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_23() + { + string source = "object () => void () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.ObjectKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_24() + { + string source = "ref int (ref int x) => ref x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.RefExpression); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_25() + { + string source = "ref D () => ref int () => ref x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.RefExpression); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.RefExpression); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_26() + { + string source = "F(a, b)"; + UsingExpression(source); + + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_27() + { + string source = "F(a,"; + UsingExpression(source, + // (1,5): error CS1733: Expected expression + // F(a, + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 5), + // (1,5): error CS1026: ) expected + // F(a, + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 5)); + + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.Argument); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_28() + { + string source = "F(ref a, out b, in c)"; + UsingExpression(source); + + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.OutKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_29() + { + string source = "F(ref a,"; + UsingExpression(source, + // (1,8): error CS1001: Identifier expected + // F(ref a, + Diagnostic(ErrorCode.ERR_IdentifierExpected, ",").WithLocation(1, 8), + // (1,9): error CS1001: Identifier expected + // F(ref a, + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 9), + // (1,9): error CS1026: ) expected + // F(ref a, + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 9), + // (1,9): error CS1003: Syntax error, '=>' expected + // F(ref a, + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>", "").WithLocation(1, 9), + // (1,9): error CS1733: Expected expression + // F(ref a, + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 9)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.Parameter); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_30() + { + string source = "F(A a, B b)"; + UsingExpression(source, + // (1,5): error CS1003: Syntax error, ',' expected + // F(A a, B b) + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments(",", "").WithLocation(1, 5), + // (1,10): error CS1003: Syntax error, ',' expected + // F(A a, B b) + Diagnostic(ErrorCode.ERR_SyntaxError, "b").WithArguments(",", "").WithLocation(1, 10)); + + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_31() + { + string source = "F(ref A a, out B b, in C c)"; + UsingExpression(source, + // (1,9): error CS1003: Syntax error, ',' expected + // F(ref A a, out B b, in C c) + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments(",", "").WithLocation(1, 9), + // (1,26): error CS1003: Syntax error, ',' expected + // F(ref A a, out B b, in C c) + Diagnostic(ErrorCode.ERR_SyntaxError, "c").WithArguments(",", "").WithLocation(1, 26)); + + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.OutKeyword); + N(SyntaxKind.DeclarationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "b"); + } + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + N(SyntaxKind.CloseParenToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_32() + { + string source = "F(ref A a,"; + UsingExpression(source, + // (1,11): error CS1001: Identifier expected + // F(ref A a, + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 11), + // (1,11): error CS1026: ) expected + // F(ref A a, + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 11), + // (1,11): error CS1003: Syntax error, '=>' expected + // F(ref A a, + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>", "").WithLocation(1, 11), + // (1,11): error CS1733: Expected expression + // F(ref A a, + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 11)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.Parameter); + { + M(SyntaxKind.IdentifierToken); + } + M(SyntaxKind.CloseParenToken); + } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_33() + { + string source = "F(a, b) => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_34() + { + string source = "F(ref a, out b, in c) => { }"; + UsingExpression(source, + // (1,8): error CS1001: Identifier expected + // F(ref a, out b, in c) => { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, ",").WithLocation(1, 8), + // (1,15): error CS1001: Identifier expected + // F(ref a, out b, in c) => { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, ",").WithLocation(1, 15), + // (1,21): error CS1001: Identifier expected + // F(ref a, out b, in c) => { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(1, 21)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.OutKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_35() + { + string source = "F(A a, B b) => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_36() + { + string source = "F(ref A a, out B b, in C c) => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.OutKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.InKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_37() + { + string source = "async void () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_38() + { + string source = "async T () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_39() + { + string source = "static void () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_40() + { + string source = "static T () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_41() + { + string source = "async static void () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_42() + { + string source = "static async ref int () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_43() + { + string source = "async async (async async) => async"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_44() + { + string source = "[A] void () => { }"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_45() + { + string source = "[A][B] T () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void ExplicitReturnType_46() + { + string source = "[A, B] ref T () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + } +} diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs index f0034659cc1c1..1b4d061c55428 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs @@ -1273,10 +1273,10 @@ class c N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); - N(SyntaxKind.ClassKeyword); - N(SyntaxKind.IdentifierToken, "c"); - N(SyntaxKind.OpenBraceToken); { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "c"); + N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); @@ -1290,8 +1290,8 @@ class c N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); - N(SyntaxKind.OpenBraceToken); { + N(SyntaxKind.OpenBraceToken); N(SyntaxKind.LocalFunctionStatement); { N(SyntaxKind.IdentifierName); @@ -1313,18 +1313,18 @@ class c N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "await"); - N(SyntaxKind.ArgumentList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); } } } N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.MethodDeclaration); { @@ -1339,41 +1339,43 @@ class c N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); - N(SyntaxKind.OpenBraceToken); { + N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); - N(SyntaxKind.IdentifierName, "await"); - { - N(SyntaxKind.IdentifierToken, "await"); - } - N(SyntaxKind.ArgumentList); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "await"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } } M(SyntaxKind.SemicolonToken); - N(SyntaxKind.ExpressionStatement); + } + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.ObjectCreationExpression); { - N(SyntaxKind.ObjectCreationExpression); + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.NewKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "await"); - N(SyntaxKind.ArgumentList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - } + N(SyntaxKind.IdentifierToken, "await"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.MethodDeclaration); { @@ -1389,8 +1391,8 @@ class c N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); - N(SyntaxKind.OpenBraceToken); { + N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.AwaitExpression); @@ -1416,11 +1418,11 @@ class c N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "await"); - N(SyntaxKind.ArgumentList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); @@ -1441,8 +1443,8 @@ class c N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); - N(SyntaxKind.OpenBraceToken); { + N(SyntaxKind.OpenBraceToken); N(SyntaxKind.LocalFunctionStatement); { N(SyntaxKind.IdentifierName); @@ -1464,18 +1466,18 @@ class c N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "await"); - N(SyntaxKind.ArgumentList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); } } } N(SyntaxKind.SemicolonToken); } + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.MethodDeclaration); { @@ -1491,8 +1493,8 @@ class c N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); - N(SyntaxKind.OpenBraceToken); { + N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.AwaitExpression); @@ -1521,11 +1523,11 @@ class c N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "await"); - N(SyntaxKind.ArgumentList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); @@ -1533,10 +1535,10 @@ class c N(SyntaxKind.CloseBraceToken); } } + N(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.CloseBraceToken); + N(SyntaxKind.EndOfFileToken); } - N(SyntaxKind.EndOfFileToken); EOF(); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs index 93d5b99c954fb..5d7a065b1833b 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs @@ -6058,25 +6058,31 @@ public void Ternary_Expression34() N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.QuestionToken); - N(SyntaxKind.InvocationExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "m"); } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.Parameter); { N(SyntaxKind.OutKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "c"); } + M(SyntaxKind.IdentifierToken); } M(SyntaxKind.CloseParenToken); } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } } M(SyntaxKind.ColonToken); M(SyntaxKind.IdentifierName); @@ -6109,25 +6115,31 @@ public void Ternary_Expression35() N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.QuestionToken); - N(SyntaxKind.InvocationExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "m"); } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "c"); } + M(SyntaxKind.IdentifierToken); } M(SyntaxKind.CloseParenToken); } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } } M(SyntaxKind.ColonToken); M(SyntaxKind.IdentifierName); @@ -6988,33 +7000,36 @@ public void Ternary_Expression49() N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.QuestionToken); - N(SyntaxKind.InvocationExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "a"); } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Argument); + N(SyntaxKind.Parameter); { N(SyntaxKind.RefKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "a"); } + M(SyntaxKind.IdentifierToken); } N(SyntaxKind.CommaToken); - M(SyntaxKind.Argument); + M(SyntaxKind.Parameter); { - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } + M(SyntaxKind.IdentifierToken); } M(SyntaxKind.CloseParenToken); } + M(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } } M(SyntaxKind.ColonToken); M(SyntaxKind.IdentifierName); From 82ef008dd6d4df670057013d238bcda81c6a2837 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Tue, 1 Jun 2021 20:55:59 -0700 Subject: [PATCH 2/6] More tests --- .../CSharp/Portable/Parser/LanguageParser.cs | 108 +- .../Test/Semantic/Semantics/NameOfTests.cs | 24 +- .../Parsing/LambdaParameterParsingTests.cs | 221 +- .../Parsing/LambdaReturnTypeParsingTests.cs | 2135 ++++++++++++++--- .../Parsing/LocalFunctionParsingTests.cs | 31 +- .../Test/Syntax/Parsing/ScriptParsingTests.cs | 43 +- 6 files changed, 2045 insertions(+), 517 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 9eb616dae5693..751f0371a0791 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.Contracts; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.Text; @@ -6317,6 +6316,7 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy { Debug.Assert(mode != ParseTypeMode.NewExpression); ScanTypeFlags result; + bool isFunctionPointer = false; if (this.CurrentToken.Kind == SyntaxKind.RefKeyword) { @@ -6406,6 +6406,7 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy } else if (IsFunctionPointerStart()) { + isFunctionPointer = true; result = ScanFunctionPointerType(out lastTokenOfType); } else @@ -6422,7 +6423,8 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy { case SyntaxKind.QuestionToken when lastTokenOfType.Kind != SyntaxKind.QuestionToken && // don't allow `Type??` - lastTokenOfType.Kind != SyntaxKind.AsteriskToken: // don't allow `Type*?` + lastTokenOfType.Kind != SyntaxKind.AsteriskToken && // don't allow `Type*?` + !isFunctionPointer: // don't allow `delegate*<...>?` lastTokenOfType = this.EatToken(); result = ScanTypeFlags.NullableType; break; @@ -6446,6 +6448,7 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy goto done; default: lastTokenOfType = this.EatToken(); + isFunctionPointer = false; if (result == ScanTypeFlags.GenericTypeOrExpression || result == ScanTypeFlags.NonGenericTypeOrExpression) { result = ScanTypeFlags.PointerOrMultiplication; @@ -6472,6 +6475,7 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy } lastTokenOfType = this.EatToken(); + isFunctionPointer = false; result = ScanTypeFlags.MustBeType; break; default: @@ -9726,7 +9730,6 @@ private bool IsPossibleExpression() return IsPossibleExpression(allowBinaryExpressions: true, allowAssignmentExpressions: true); } - // PROTOTYPE: Does this need to be updated to include lambdas with explicit return type? private bool IsPossibleExpression(bool allowBinaryExpressions, bool allowAssignmentExpressions) { SyntaxKind tk = this.CurrentToken.Kind; @@ -9769,7 +9772,7 @@ private bool IsPossibleExpression(bool allowBinaryExpressions, bool allowAssignm // expression (whether it is used as an identifier or a keyword). return this.IsTrueIdentifier() || (this.CurrentToken.ContextualKind == SyntaxKind.FromKeyword); default: - return (IsPredefinedType(tk) && tk != SyntaxKind.VoidKeyword) + return IsPredefinedType(tk) || SyntaxFacts.IsAnyUnaryExpression(tk) || (allowBinaryExpressions && SyntaxFacts.IsBinaryExpression(tk)) || (allowAssignmentExpressions && SyntaxFacts.IsAssignmentExpressionOperatorToken(tk)); @@ -10422,9 +10425,9 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) { return this.ParseAnonymousMethodExpression(); } - else if (this.IsPossibleLambdaExpression(precedence)) + else if (this.IsPossibleLambdaExpression(precedence) && this.TryParseLambdaExpression() is { } lambda) { - return this.ParseLambdaExpression(); + return lambda; } else if (this.IsPossibleDeconstructionLeft(precedence)) { @@ -10469,6 +10472,7 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) case SyntaxKind.StackAllocKeyword: return this.ParseStackAllocExpression(); case SyntaxKind.DelegateKeyword: + // check for lambda expression with explicit function pointer return type if (this.IsPossibleLambdaExpression(precedence)) { return this.ParseLambdaExpression(); @@ -10601,7 +10605,8 @@ private bool IsPossibleAnonymousMethodExpression() tokenIndex++; } - return this.PeekToken(tokenIndex).Kind == SyntaxKind.DelegateKeyword; + return this.PeekToken(tokenIndex).Kind == SyntaxKind.DelegateKeyword && + this.PeekToken(tokenIndex + 1).Kind != SyntaxKind.AsteriskToken; } private ExpressionSyntax ParsePostFixExpression(ExpressionSyntax expr) @@ -11153,22 +11158,14 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) var resetPoint = this.GetResetPoint(); try { - bool foundParameterModifier = false; - // do we have the following, possibly with attributes before the parameter: - // case 1: ( T x , ... ) => - // case 2: ( T x ) => - // case 3: ( out T x, - // case 4: ( ref T x, - // case 5: ( out T x ) => - // case 6: ( ref T x ) => - // case 7: ( in T x ) => + // case 1: ( T x [, ...]) => + // case 2: ( out T x [, ...]) => + // case 3: ( ref T x [, ...]) => + // case 4: ( in T x [, ...]) => // // if so then parse it as a lambda - // Note: in the first two cases, we cannot distinguish a lambda from a tuple expression - // containing declaration expressions, so we scan forwards to the `=>` so we know for sure. - while (true) { // Advance past the open paren or comma. @@ -11176,13 +11173,12 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) _ = ParseAttributeDeclarations(); - // Eat 'out' or 'ref' for cases [3, 6]. Even though not allowed in a lambda, + // Eat 'out', 'ref', and 'in'. Even though not allowed in a lambda, // we treat `params` similarly for better error recovery. switch (this.CurrentToken.Kind) { case SyntaxKind.RefKeyword: this.EatToken(); - foundParameterModifier = true; if (this.CurrentToken.Kind == SyntaxKind.ReadOnlyKeyword) { this.EatToken(); @@ -11192,15 +11188,9 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) case SyntaxKind.InKeyword: case SyntaxKind.ParamsKeyword: this.EatToken(); - foundParameterModifier = true; break; } - if (this.CurrentToken.Kind == SyntaxKind.EndOfFileToken) - { - return foundParameterModifier; - } - // NOTE: advances CurrentToken if (this.ScanType() == ScanTypeFlags.NotType) { @@ -11215,9 +11205,6 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) switch (this.CurrentToken.Kind) { - case SyntaxKind.EndOfFileToken: - return foundParameterModifier; - case SyntaxKind.CommaToken: continue; @@ -11240,9 +11227,9 @@ private ExpressionSyntax ParseCastOrParenExpressionOrLambdaOrTuple(Precedence pr { Debug.Assert(this.CurrentToken.Kind == SyntaxKind.OpenParenToken); - if (IsPossibleLambdaExpression(precedence)) + if (IsPossibleLambdaExpression(precedence) && this.TryParseLambdaExpression() is { } lambda) { - return this.ParseLambdaExpression(); + return lambda; } var resetPoint = this.GetResetPoint(); @@ -11266,12 +11253,6 @@ private ExpressionSyntax ParseCastOrParenExpressionOrLambdaOrTuple(Precedence pr } } - this.Reset(ref resetPoint); - if (this.ScanExplicitlyTypedLambda(precedence)) - { - return this.ParseLambdaExpression(); - } - // Doesn't look like a cast, so parse this as a parenthesized expression or tuple. { this.Reset(ref resetPoint); @@ -11518,7 +11499,8 @@ private bool IsPossibleLambdaExpression(Precedence precedence) // Have checked all the static forms. And have checked for the basic `a => a` form. // At this point we have must be on 'async' or an explicit return type for this to still be a lambda. - if (this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword) + if (this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword && + IsAnonymousFunctionAsyncModifier()) { EatToken(); } @@ -11526,7 +11508,7 @@ private bool IsPossibleLambdaExpression(Precedence precedence) var nestedResetPoint = this.GetResetPoint(); try { - var st = ScanType(); // PROTOTYPE: Are default arguments to ScanType() correct? + var st = ScanType(); if (st == ScanTypeFlags.NotType || this.CurrentToken.Kind != SyntaxKind.OpenParenToken) { this.Reset(ref nestedResetPoint); @@ -12363,7 +12345,7 @@ private SyntaxList ParseAnonymousFunctionModifiers() } if (this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword && - this.PeekToken(1).Kind != SyntaxKind.EqualsGreaterThanToken) + IsAnonymousFunctionAsyncModifier()) { var asyncToken = this.EatContextualToken(SyntaxKind.AsyncKeyword); asyncToken = CheckFeatureAvailability(asyncToken, MessageID.IDS_FeatureAsync); @@ -12379,6 +12361,50 @@ private SyntaxList ParseAnonymousFunctionModifiers() return result; } + private bool IsAnonymousFunctionAsyncModifier() + { + Debug.Assert(this.CurrentToken.ContextualKind == SyntaxKind.AsyncKeyword); + + switch (this.PeekToken(1).Kind) + { + case SyntaxKind.OpenParenToken: + case SyntaxKind.IdentifierToken: + case SyntaxKind.StaticKeyword: + case SyntaxKind.RefKeyword: + case SyntaxKind.DelegateKeyword: + return true; + case var kind: + return IsPredefinedType(kind); + }; + } + + /// + /// Parse expected lambda expression but assume `x ? () => y :` is a conditional + /// expression rather than a lambda expression with an explicit return type and + /// return null in that case only. + /// + private LambdaExpressionSyntax TryParseLambdaExpression() + { + var resetPoint = this.GetResetPoint(); + try + { + var result = ParseLambdaExpression(); + + if (this.CurrentToken.Kind == SyntaxKind.ColonToken && + result is ParenthesizedLambdaExpressionSyntax { ReturnType: NullableTypeSyntax { } }) + { + this.Reset(ref resetPoint); + return null; + } + + return result; + } + finally + { + this.Release(ref resetPoint); + } + } + private LambdaExpressionSyntax ParseLambdaExpression() { var attributes = ParseAttributeDeclarations(); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 0a0dc8c945aac..de720a32d6e23 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -5,10 +5,8 @@ #nullable disable using System; -using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; -using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using System.Threading; @@ -243,33 +241,15 @@ class Test // (12,20): error CS1525: Invalid expression term 'int' // s = nameof(int); Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(12, 20), - // (13,20): error CS1026: ) expected + // (13,20): error CS1525: Invalid expression term 'void' // s = nameof(void); - Diagnostic(ErrorCode.ERR_CloseParenExpected, "void").WithLocation(13, 20), - // (13,20): error CS1002: ; expected - // s = nameof(void); - Diagnostic(ErrorCode.ERR_SemicolonExpected, "void").WithLocation(13, 20), - // (13,20): error CS1547: Keyword 'void' cannot be used in this context - // s = nameof(void); - Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(13, 20), - // (13,24): error CS1001: Identifier expected - // s = nameof(void); - Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(13, 24), - // (13,24): error CS1002: ; expected - // s = nameof(void); - Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(13, 24), - // (13,24): error CS1513: } expected - // s = nameof(void); - Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(13, 24), + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "void").WithArguments("void").WithLocation(13, 20), // (17,66): error CS1031: Type expected // s = nameof(System.Collections.Generic.Dictionary.KeyCollection); Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(17, 66), // (11,27): error CS0305: Using the generic type 'Action' requires 1 type arguments // s = nameof(System.Action<>); Diagnostic(ErrorCode.ERR_BadArity, "Action<>").WithArguments("System.Action", "type", "1").WithLocation(11, 27), - // (13,13): error CS0103: The name 'nameof' does not exist in the current context - // s = nameof(void); - Diagnostic(ErrorCode.ERR_NameNotInContext, "nameof").WithArguments("nameof").WithLocation(13, 13), // (16,20): error CS0103: The name 'List' does not exist in the current context // s = nameof(List.Enumerator); Diagnostic(ErrorCode.ERR_NameNotInContext, "List").WithArguments("List").WithLocation(16, 20), diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs index 49f8196a6339a..dd566a968bc30 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaParameterParsingTests.cs @@ -37,7 +37,7 @@ void Goo() { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { @@ -45,7 +45,7 @@ void Goo() { { N(SyntaxKind.VoidKeyword); } - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Goo"); N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); @@ -62,12 +62,12 @@ void Goo() { { N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "System"); } N(SyntaxKind.DotToken); N(SyntaxKind.GenericName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Func"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); @@ -86,31 +86,18 @@ void Goo() { } N(SyntaxKind.VariableDeclarator); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "f"); N(SyntaxKind.EqualsValueClause); { N(SyntaxKind.EqualsToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ParenthesizedExpression); { - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.OutKeyword); - M(SyntaxKind.IdentifierName); // parameter type - { - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.IdentifierToken); // parameter name - } - M(SyntaxKind.CloseParenToken); - } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); // lambda body + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } + M(SyntaxKind.CloseParenToken); } } } @@ -124,6 +111,7 @@ void Goo() { } N(SyntaxKind.EndOfFileToken); } + EOF(); } [Fact] @@ -139,7 +127,7 @@ void Goo() { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { @@ -147,7 +135,7 @@ void Goo() { { N(SyntaxKind.VoidKeyword); } - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Goo"); N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); @@ -164,12 +152,12 @@ void Goo() { { N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "System"); } N(SyntaxKind.DotToken); N(SyntaxKind.GenericName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Func"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); @@ -188,37 +176,32 @@ void Goo() { } N(SyntaxKind.VariableDeclarator); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "f"); N(SyntaxKind.EqualsValueClause); { N(SyntaxKind.EqualsToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ParenthesizedExpression); { - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.OutKeyword); - N(SyntaxKind.IdentifierName); // parameter type - { - N(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.IdentifierToken); // parameter name - } - M(SyntaxKind.CloseParenToken); - } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); // lambda body + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } + M(SyntaxKind.CloseParenToken); } } } } M(SyntaxKind.SemicolonToken); } + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + M(SyntaxKind.SemicolonToken); + } M(SyntaxKind.CloseBraceToken); } } @@ -226,6 +209,7 @@ void Goo() { } N(SyntaxKind.EndOfFileToken); } + EOF(); } [Fact] @@ -241,7 +225,7 @@ void Goo() { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { @@ -249,7 +233,7 @@ void Goo() { { N(SyntaxKind.VoidKeyword); } - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Goo"); N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); @@ -266,12 +250,12 @@ void Goo() { { N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "System"); } N(SyntaxKind.DotToken); N(SyntaxKind.GenericName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Func"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); @@ -290,37 +274,39 @@ void Goo() { } N(SyntaxKind.VariableDeclarator); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "f"); N(SyntaxKind.EqualsValueClause); { N(SyntaxKind.EqualsToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ParenthesizedExpression); { - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.OutKeyword); - N(SyntaxKind.IdentifierName); // parameter type - { - N(SyntaxKind.IdentifierToken); - } - N(SyntaxKind.IdentifierToken); // parameter name - } - M(SyntaxKind.CloseParenToken); - } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); // lambda body + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } + M(SyntaxKind.CloseParenToken); } } } } M(SyntaxKind.SemicolonToken); } + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + M(SyntaxKind.SemicolonToken); + } M(SyntaxKind.CloseBraceToken); } } @@ -328,6 +314,7 @@ void Goo() { } N(SyntaxKind.EndOfFileToken); } + EOF(); } [Fact] @@ -343,7 +330,7 @@ void Goo() { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { @@ -351,7 +338,7 @@ void Goo() { { N(SyntaxKind.VoidKeyword); } - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Goo"); N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); @@ -368,12 +355,12 @@ void Goo() { { N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "System"); } N(SyntaxKind.DotToken); N(SyntaxKind.GenericName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Func"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); @@ -392,37 +379,39 @@ void Goo() { } N(SyntaxKind.VariableDeclarator); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "f"); N(SyntaxKind.EqualsValueClause); { N(SyntaxKind.EqualsToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ParenthesizedExpression); { - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.OutKeyword); - N(SyntaxKind.IdentifierName); // parameter type - { - N(SyntaxKind.IdentifierToken); - } - N(SyntaxKind.IdentifierToken); // parameter name - } - M(SyntaxKind.CloseParenToken); - } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); // lambda body + N(SyntaxKind.OpenParenToken); + M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } + M(SyntaxKind.CloseParenToken); } } } } M(SyntaxKind.SemicolonToken); } + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "c"); + } + } + M(SyntaxKind.SemicolonToken); + } M(SyntaxKind.CloseBraceToken); } } @@ -430,6 +419,7 @@ void Goo() { } N(SyntaxKind.EndOfFileToken); } + EOF(); } [Fact] @@ -445,7 +435,7 @@ void Goo() { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { @@ -453,7 +443,7 @@ void Goo() { { N(SyntaxKind.VoidKeyword); } - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Goo"); N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); @@ -470,12 +460,12 @@ void Goo() { { N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "System"); } N(SyntaxKind.DotToken); N(SyntaxKind.GenericName); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "Func"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); @@ -494,42 +484,44 @@ void Goo() { } N(SyntaxKind.VariableDeclarator); { - N(SyntaxKind.IdentifierToken); + N(SyntaxKind.IdentifierToken, "f"); N(SyntaxKind.EqualsValueClause); { N(SyntaxKind.EqualsToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ParenthesizedExpression); { - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.OutKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken); - } - N(SyntaxKind.IdentifierToken); - } - N(SyntaxKind.CommaToken); - M(SyntaxKind.Parameter); - { - M(SyntaxKind.IdentifierToken); - } - M(SyntaxKind.CloseParenToken); - } - M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.OpenParenToken); M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } + M(SyntaxKind.CloseParenToken); } } } } M(SyntaxKind.SemicolonToken); } + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } M(SyntaxKind.CloseBraceToken); } } @@ -537,6 +529,7 @@ void Goo() { } N(SyntaxKind.EndOfFileToken); } + EOF(); } [Fact, WorkItem(14167, "https://github.com/dotnet/roslyn/issues/14167")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs index 31c413cb11880..56d4a56455e64 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Xunit; using Xunit.Abstractions; @@ -22,10 +23,22 @@ protected override CSharpSyntaxNode ParseNode(string text, CSharpParseOptions? o return SyntaxFactory.ParseExpression(text, options: options); } - [Fact] - public void ExplicitReturnType_01() + public static IEnumerable AsyncAndStaticModifiers() + { + yield return getModifiers(""); + yield return getModifiers("async", SyntaxKind.AsyncKeyword); + yield return getModifiers("static", SyntaxKind.StaticKeyword); + yield return getModifiers("async static", SyntaxKind.AsyncKeyword, SyntaxKind.StaticKeyword); + yield return getModifiers("static async", SyntaxKind.StaticKeyword, SyntaxKind.AsyncKeyword); + + static object[] getModifiers(string modifiers, params SyntaxKind[] modifierKinds) => new object[] { modifiers, modifierKinds }; + } + + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void IdentifierReturnType_01(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "T () => default"; + string source = modifiers + " T () => default"; UsingExpression(source, TestOptions.Regular9); verify(); @@ -36,6 +49,10 @@ void verify() { N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "T"); @@ -56,7 +73,7 @@ void verify() } [Fact] - public void ExplicitReturnType_02() + public void IdentifierReturnType_02() { string source = "T (x) => { return x; }"; UsingExpression(source, TestOptions.Regular9); @@ -103,7 +120,7 @@ void verify() } [Fact] - public void ExplicitReturnType_03() + public void IdentifierReturnType_03() { string source = "T (T x) => x"; UsingExpression(source, TestOptions.Regular9); @@ -144,7 +161,42 @@ void verify() } [Fact] - public void ExplicitReturnType_04() + public void IdentifierReturnType_04() + { + string source = "var (x, y) => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "y"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void IdentifierReturnType_05() { string source = "T x => y"; UsingExpression(source, TestOptions.Regular9, @@ -169,14 +221,19 @@ void verify() } } - [Fact] - public void ExplicitReturnType_05() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void PrimitiveReturnType_01(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "int (_) => 0"; + string source = modifiers + " int (_) => 0"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); @@ -199,14 +256,19 @@ public void ExplicitReturnType_05() EOF(); } - [Fact] - public void ExplicitReturnType_06() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void PrimitiveReturnType_02(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "void () => { }"; + string source = modifiers + " void () => { }"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); @@ -226,14 +288,19 @@ public void ExplicitReturnType_06() EOF(); } - [Fact] - public void ExplicitReturnType_07() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void ArrayReturnType(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "T[] () => null"; + string source = modifiers + " T[] () => null"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.ArrayType); { N(SyntaxKind.IdentifierName); @@ -256,29 +323,1252 @@ public void ExplicitReturnType_07() N(SyntaxKind.CloseParenToken); } N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.NullLiteralExpression); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void PointerReturnType_01(string modifiers, params SyntaxKind[] modifierKinds) + { + string source = modifiers + " T* () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + foreach (var modifier in modifierKinds) + { + N(modifier); + } + N(SyntaxKind.PointerType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void PointerReturnType_02() + { + string source = "int* () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void PointerReturnType_03() + { + string source = "void* () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.PointerType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.AsteriskToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void FunctionPointerReturnType(string modifiers, params SyntaxKind[] modifierKinds) + { + string source = modifiers + " delegate* () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + foreach (var modifier in modifierKinds) + { + N(modifier); + } + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_01A() + { + string source = "int? () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_01B() + { + string source = "int? () => x : y"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token ':' + // int? () => x : y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "int? () => x").WithArguments(":").WithLocation(1, 1)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_02A() + { + string source = "int[]? () => null"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_02B() + { + string source = "int[]? () => x : y"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token ':' + // int[]? () => x : y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "int[]? () => x").WithArguments(":").WithLocation(1, 1)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_03A() + { + string source = "int.MaxValue? () => null"; + UsingExpression(source, + // (1,25): error CS1003: Syntax error, ':' expected + // int.MaxValue? () => null + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 25), + // (1,25): error CS1733: Expected expression + // int.MaxValue? () => null + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 25)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MaxValue"); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NullLiteralExpression); + { + N(SyntaxKind.NullKeyword); + } + } + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_03B() + { + string source = "int.MaxValue? () => x : y"; + UsingExpression(source); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "MaxValue"); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_04A() + { + string source = "T? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_04B() + { + string source = "T? () => x : y"; + UsingExpression(source); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_05A() + { + string source = "(x, y)? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_05B() + { + string source = "(x, y)? () => x : z"; + UsingExpression(source); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.TupleExpression); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "z"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_06A() + { + string source = "T[]? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_06B() + { + string source = "T[]? () => x : y"; + UsingExpression(source, + // (1,3): error CS0443: Syntax error; value expected + // T[]? () => x : y + Diagnostic(ErrorCode.ERR_ValueExpected, "]").WithLocation(1, 3)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + M(SyntaxKind.Argument); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_07A() + { + string source = "A? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_07B() + { + string source = "A? () => x : y"; + UsingExpression(source); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_08A() + { + string source = "int*? () => x"; + UsingExpression(source, + // (1,1): error CS1525: Invalid expression term 'int' + // int*? () => x + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(1, 1), + // (1,5): error CS1525: Invalid expression term '?' + // int*? () => x + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(1, 5), + // (1,14): error CS1003: Syntax error, ':' expected + // int*? () => x + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 14), + // (1,14): error CS1733: Expected expression + // int*? () => x + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 14)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.MultiplyExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_08B() + { + string source = "int*? () => x : y"; + UsingExpression(source, + // (1,1): error CS1525: Invalid expression term 'int' + // int*? () => x : y + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(1, 1), + // (1,5): error CS1525: Invalid expression term '?' + // int*? () => x : y + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(1, 5)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.MultiplyExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.AsteriskToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_09A() + { + string source = "delegate*? () => x"; + UsingExpression(source, + // (1,9): error CS1514: { expected + // delegate*? () => x + Diagnostic(ErrorCode.ERR_LbraceExpected, "*").WithLocation(1, 9), + // (1,9): warning CS8848: Operator '*' cannot be used here due to precedence. Use parentheses to disambiguate. + // delegate*? () => x + Diagnostic(ErrorCode.WRN_PrecedenceInversion, "*").WithArguments("*").WithLocation(1, 9), + // (1,10): error CS1525: Invalid expression term '<' + // delegate*? () => x + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(1, 10), + // (1,11): error CS1525: Invalid expression term 'void' + // delegate*? () => x + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "void").WithArguments("void").WithLocation(1, 11), + // (1,16): error CS1525: Invalid expression term '?' + // delegate*? () => x + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(1, 16), + // (1,25): error CS1003: Syntax error, ':' expected + // delegate*? () => x + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 25), + // (1,25): error CS1733: Expected expression + // delegate*? () => x + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 25)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.GreaterThanExpression); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.MultiplyExpression); + { + N(SyntaxKind.AnonymousMethodExpression); + { + N(SyntaxKind.DelegateKeyword); + M(SyntaxKind.Block); + { + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.AsteriskToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_09B() + { + string source = "delegate*? () => x : y"; + UsingExpression(source, + // (1,9): error CS1514: { expected + // delegate*? () => x : y + Diagnostic(ErrorCode.ERR_LbraceExpected, "*").WithLocation(1, 9), + // (1,9): warning CS8848: Operator '*' cannot be used here due to precedence. Use parentheses to disambiguate. + // delegate*? () => x : y + Diagnostic(ErrorCode.WRN_PrecedenceInversion, "*").WithArguments("*").WithLocation(1, 9), + // (1,10): error CS1525: Invalid expression term '<' + // delegate*? () => x : y + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(1, 10), + // (1,11): error CS1525: Invalid expression term 'void' + // delegate*? () => x : y + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "void").WithArguments("void").WithLocation(1, 11), + // (1,16): error CS1525: Invalid expression term '?' + // delegate*? () => x : y + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(1, 16)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.GreaterThanExpression); + { + N(SyntaxKind.LessThanExpression); + { + N(SyntaxKind.MultiplyExpression); + { + N(SyntaxKind.AnonymousMethodExpression); + { + N(SyntaxKind.DelegateKeyword); + M(SyntaxKind.Block); + { + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.AsteriskToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_10A() + { + string source = "static T? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_10B() + { + string source = "static T? () => x : y"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token ':' + // static T? () => x : y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "static T? () => x").WithArguments(":").WithLocation(1, 1)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_11A() + { + string source = "async? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_11B() + { + string source = "async? () => x : y"; + UsingExpression(source); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_12A() + { + string source = "async T? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AsyncKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_12B() + { + string source = "async T? () => x : y"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token 'T' + // async T? () => x : y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "async").WithArguments("T").WithLocation(1, 1)); + + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_13A() + { + string source = "[A] T? () => x"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.NullKeyword); + N(SyntaxKind.IdentifierToken, "x"); } } EOF(); } [Fact] - public void ExplicitReturnType_08() + public void NullableReturnTypeOrConditional_13B() { - string source = "T* () => default"; - UsingExpression(source); + string source = "[A] T? () => x : y"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token ':' + // [A] T? () => x : y + Diagnostic(ErrorCode.ERR_UnexpectedToken, "[A] T? () => x").WithArguments(":").WithLocation(1, 1)); N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.PointerType); + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.NullableType); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "T"); } - N(SyntaxKind.AsteriskToken); + N(SyntaxKind.QuestionToken); } N(SyntaxKind.ParameterList); { @@ -286,115 +1576,166 @@ public void ExplicitReturnType_08() N(SyntaxKind.CloseParenToken); } N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.DefaultKeyword); + N(SyntaxKind.IdentifierToken, "x"); } } EOF(); } [Fact] - public void ExplicitReturnType_09() + public void NullableReturnTypeOrConditional_14A() { - string source = "delegate* () => default"; - UsingExpression(source); - - N(SyntaxKind.ParenthesizedLambdaExpression); + string source = "b? c? () => x : y"; + UsingExpression(source, + // (1,18): error CS1003: Syntax error, ':' expected + // b? c? () => x : y + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 18), + // (1,18): error CS1733: Expected expression + // b? c? () => x : y + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 18)); + + N(SyntaxKind.ConditionalExpression); { - N(SyntaxKind.FunctionPointerType); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.DelegateKeyword); - N(SyntaxKind.AsteriskToken); - N(SyntaxKind.FunctionPointerParameterList); + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.LessThanToken); - N(SyntaxKind.FunctionPointerParameter); + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.VoidKeyword); - } + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); } - N(SyntaxKind.GreaterThanToken); + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); } } - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); { - N(SyntaxKind.DefaultKeyword); + M(SyntaxKind.IdentifierToken); } } EOF(); } [Fact] - public void ExplicitReturnType_10() + public void NullableReturnTypeOrConditional_14B() { - string source = "T? () => null"; + string source = "b? c? () => x : y : z"; UsingExpression(source); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ConditionalExpression); { - N(SyntaxKind.NullableType); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ConditionalExpression); { N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken, "T"); + N(SyntaxKind.IdentifierToken, "c"); } N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } } - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.NullLiteralExpression); + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.NullKeyword); + N(SyntaxKind.IdentifierToken, "z"); } } EOF(); } [Fact] - public void ExplicitReturnType_11() + public void NullableReturnTypeOrConditional_14C() { - string source = "int? () => null"; + string source = "b? (c? () => x) : y"; UsingExpression(source); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.ConditionalExpression); { - N(SyntaxKind.NullableType); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } - N(SyntaxKind.QuestionToken); + N(SyntaxKind.IdentifierToken, "b"); } - N(SyntaxKind.ParameterList); + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedExpression); { N(SyntaxKind.OpenParenToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "c"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } N(SyntaxKind.CloseParenToken); } - N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.NullLiteralExpression); + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.NullKeyword); + N(SyntaxKind.IdentifierToken, "y"); } } EOF(); } [Fact] - public void ExplicitReturnType_12() + public void QualifiedNameReturnType_01() { string source = "A.B () => null"; UsingExpression(source); @@ -427,14 +1768,19 @@ public void ExplicitReturnType_12() EOF(); } - [Fact] - public void ExplicitReturnType_13() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void QualifiedNameReturnType_02(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "A::B () => null"; + string source = modifiers + " A::B () => null"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.AliasQualifiedName); { N(SyntaxKind.IdentifierName); @@ -462,7 +1808,7 @@ public void ExplicitReturnType_13() } [Fact] - public void ExplicitReturnType_14() + public void QualifiedNameReturnType_03() { string source = "global::T () => null"; UsingExpression(source); @@ -496,7 +1842,7 @@ public void ExplicitReturnType_14() } [Fact] - public void ExplicitReturnType_15() + public void GenericReturnType_01() { string source = "A () => null"; UsingExpression(source); @@ -530,14 +1876,19 @@ public void ExplicitReturnType_15() EOF(); } - [Fact] - public void ExplicitReturnType_16() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void GenericReturnType_02(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "A.C () => null"; + string source = modifiers + " A.C () => null"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.QualifiedName); { N(SyntaxKind.GenericName); @@ -573,30 +1924,35 @@ public void ExplicitReturnType_16() EOF(); } - [Fact] - public void ExplicitReturnType_17() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void TupleReturnType_01(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "(int, object) () => default"; + string source = modifiers + " (x, y) (x, y) => (x, y)"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.TupleType); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.TupleElement); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IntKeyword); + N(SyntaxKind.IdentifierToken, "x"); } } N(SyntaxKind.CommaToken); N(SyntaxKind.TupleElement); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.ObjectKeyword); + N(SyntaxKind.IdentifierToken, "y"); } } N(SyntaxKind.CloseParenToken); @@ -604,19 +1960,44 @@ public void ExplicitReturnType_17() N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "y"); + } N(SyntaxKind.CloseParenToken); } N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); + N(SyntaxKind.TupleExpression); { - N(SyntaxKind.DefaultKeyword); + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + N(SyntaxKind.CloseParenToken); } } EOF(); } [Fact] - public void ExplicitReturnType_18() + public void TupleReturnType_02() { string source = "(int x, object y) () => default"; UsingExpression(source); @@ -660,77 +2041,7 @@ public void ExplicitReturnType_18() } [Fact] - public void ExplicitReturnType_19() - { - string source = "var (x, y) => default"; - UsingExpression(source); - - N(SyntaxKind.ParenthesizedLambdaExpression); - { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "var"); - } - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.IdentifierToken, "x"); - } - N(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.IdentifierToken, "y"); - } - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); - { - N(SyntaxKind.DefaultKeyword); - } - } - EOF(); - } - - [Fact] - public void ExplicitReturnType_20() - { - string source = "int (x, y) => default"; - UsingExpression(source); - - N(SyntaxKind.ParenthesizedLambdaExpression); - { - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.IdentifierToken, "x"); - } - N(SyntaxKind.CommaToken); - N(SyntaxKind.Parameter); - { - N(SyntaxKind.IdentifierToken, "y"); - } - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); - { - N(SyntaxKind.DefaultKeyword); - } - } - EOF(); - } - - [Fact] - public void ExplicitReturnType_21() + public void Nested_01() { string source = "A () => () => { }"; UsingExpression(source); @@ -766,7 +2077,7 @@ public void ExplicitReturnType_21() } [Fact] - public void ExplicitReturnType_22() + public void Nested_02() { string source = "A () => B () => null"; UsingExpression(source); @@ -805,7 +2116,7 @@ public void ExplicitReturnType_22() } [Fact] - public void ExplicitReturnType_23() + public void Nested_03() { string source = "object () => void () => { }"; UsingExpression(source); @@ -844,14 +2155,19 @@ public void ExplicitReturnType_23() EOF(); } - [Fact] - public void ExplicitReturnType_24() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void Ref_01(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "ref int (ref int x) => ref x"; + string source = modifiers + " ref int (ref int x) => ref x"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.RefType); { N(SyntaxKind.RefKeyword); @@ -888,7 +2204,7 @@ public void ExplicitReturnType_24() } [Fact] - public void ExplicitReturnType_25() + public void Ref_02() { string source = "ref D () => ref int () => ref x"; UsingExpression(source); @@ -939,7 +2255,7 @@ public void ExplicitReturnType_25() } [Fact] - public void ExplicitReturnType_26() + public void InvocationOrLambda_01() { string source = "F(a, b)"; UsingExpression(source); @@ -975,7 +2291,7 @@ public void ExplicitReturnType_26() } [Fact] - public void ExplicitReturnType_27() + public void InvocationOrLambda_02() { string source = "F(a,"; UsingExpression(source, @@ -1017,7 +2333,7 @@ public void ExplicitReturnType_27() } [Fact] - public void ExplicitReturnType_28() + public void InvocationOrLambda_03() { string source = "F(ref a, out b, in c)"; UsingExpression(source); @@ -1064,62 +2380,50 @@ public void ExplicitReturnType_28() } [Fact] - public void ExplicitReturnType_29() + public void InvocationOrLambda_04() { - string source = "F(ref a,"; - UsingExpression(source, - // (1,8): error CS1001: Identifier expected - // F(ref a, - Diagnostic(ErrorCode.ERR_IdentifierExpected, ",").WithLocation(1, 8), - // (1,9): error CS1001: Identifier expected + string source = "F(ref a,"; + UsingExpression(source, + // (1,9): error CS1733: Expected expression // F(ref a, - Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 9), + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 9), // (1,9): error CS1026: ) expected // F(ref a, - Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 9), - // (1,9): error CS1003: Syntax error, '=>' expected - // F(ref a, - Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>", "").WithLocation(1, 9), - // (1,9): error CS1733: Expected expression - // F(ref a, - Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 9)); + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 9)); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.InvocationExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "F"); } - N(SyntaxKind.ParameterList); + N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); + N(SyntaxKind.Argument); { N(SyntaxKind.RefKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "a"); } - M(SyntaxKind.IdentifierToken); } N(SyntaxKind.CommaToken); - M(SyntaxKind.Parameter); + M(SyntaxKind.Argument); { - M(SyntaxKind.IdentifierToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } } M(SyntaxKind.CloseParenToken); } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } } EOF(); } [Fact] - public void ExplicitReturnType_30() + public void InvocationOrLambda_05() { string source = "F(A a, B b)"; UsingExpression(source, @@ -1177,7 +2481,7 @@ public void ExplicitReturnType_30() } [Fact] - public void ExplicitReturnType_31() + public void InvocationOrLambda_06() { string source = "F(ref A a, out B b, in C c)"; UsingExpression(source, @@ -1253,59 +2557,61 @@ public void ExplicitReturnType_31() } [Fact] - public void ExplicitReturnType_32() + public void InvocationOrLambda_07() { string source = "F(ref A a,"; UsingExpression(source, - // (1,11): error CS1001: Identifier expected - // F(ref A a, - Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 11), - // (1,11): error CS1026: ) expected - // F(ref A a, - Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 11), - // (1,11): error CS1003: Syntax error, '=>' expected + // (1,9): error CS1003: Syntax error, ',' expected // F(ref A a, - Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("=>", "").WithLocation(1, 11), + Diagnostic(ErrorCode.ERR_SyntaxError, "a").WithArguments(",", "").WithLocation(1, 9), // (1,11): error CS1733: Expected expression // F(ref A a, - Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 11)); + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 11), + // (1,11): error CS1026: ) expected + // F(ref A a, + Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 11)); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.InvocationExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "F"); } - N(SyntaxKind.ParameterList); + N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); + N(SyntaxKind.Argument); { N(SyntaxKind.RefKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "A"); } - N(SyntaxKind.IdentifierToken, "a"); + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "a"); + } } N(SyntaxKind.CommaToken); - M(SyntaxKind.Parameter); + M(SyntaxKind.Argument); { - M(SyntaxKind.IdentifierToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } } M(SyntaxKind.CloseParenToken); } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } } EOF(); } [Fact] - public void ExplicitReturnType_33() + public void InvocationOrLambda_08() { string source = "F(a, b) => { }"; UsingExpression(source); @@ -1341,7 +2647,7 @@ public void ExplicitReturnType_33() } [Fact] - public void ExplicitReturnType_34() + public void InvocationOrLambda_09() { string source = "F(ref a, out b, in c) => { }"; UsingExpression(source, @@ -1406,7 +2712,7 @@ public void ExplicitReturnType_34() } [Fact] - public void ExplicitReturnType_35() + public void InvocationOrLambda_10() { string source = "F(A a, B b) => { }"; UsingExpression(source); @@ -1450,7 +2756,7 @@ public void ExplicitReturnType_35() } [Fact] - public void ExplicitReturnType_36() + public void InvocationOrLambda_11() { string source = "F(ref A a, out B b, in C c) => { }"; UsingExpression(source); @@ -1506,17 +2812,28 @@ public void ExplicitReturnType_36() } [Fact] - public void ExplicitReturnType_37() + public void Async_01() { - string source = "async void () => { }"; + string source = "async[] () => { }"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.AsyncKeyword); - N(SyntaxKind.PredefinedType); + N(SyntaxKind.ArrayType); { - N(SyntaxKind.VoidKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } } N(SyntaxKind.ParameterList); { @@ -1534,44 +2851,20 @@ public void ExplicitReturnType_37() } [Fact] - public void ExplicitReturnType_38() - { - string source = "async T () => default"; - UsingExpression(source); - - N(SyntaxKind.ParenthesizedLambdaExpression); - { - N(SyntaxKind.AsyncKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "T"); - } - N(SyntaxKind.ParameterList); - { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); - } - N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); - { - N(SyntaxKind.DefaultKeyword); - } - } - EOF(); - } - - [Fact] - public void ExplicitReturnType_39() + public void Async_02() { - string source = "static void () => { }"; + string source = "async* () => { }"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.StaticKeyword); - N(SyntaxKind.PredefinedType); + N(SyntaxKind.PointerType); { - N(SyntaxKind.VoidKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.AsteriskToken); } N(SyntaxKind.ParameterList); { @@ -1589,17 +2882,24 @@ public void ExplicitReturnType_39() } [Fact] - public void ExplicitReturnType_40() + public void Async_03() { - string source = "static T () => default"; + string source = "async.B () => { }"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.StaticKeyword); - N(SyntaxKind.IdentifierName); + N(SyntaxKind.QualifiedName); { - N(SyntaxKind.IdentifierToken, "T"); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "B"); + } } N(SyntaxKind.ParameterList); { @@ -1607,27 +2907,35 @@ public void ExplicitReturnType_40() N(SyntaxKind.CloseParenToken); } N(SyntaxKind.EqualsGreaterThanToken); - N(SyntaxKind.DefaultLiteralExpression); + N(SyntaxKind.Block); { - N(SyntaxKind.DefaultKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); } } EOF(); } [Fact] - public void ExplicitReturnType_41() + public void Async_04() { - string source = "async static void () => { }"; + string source = "async () => { }"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.AsyncKeyword); - N(SyntaxKind.StaticKeyword); - N(SyntaxKind.PredefinedType); + N(SyntaxKind.GenericName); { - N(SyntaxKind.VoidKeyword); + N(SyntaxKind.IdentifierToken, "async"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.GreaterThanToken); + } } N(SyntaxKind.ParameterList); { @@ -1645,22 +2953,16 @@ public void ExplicitReturnType_41() } [Fact] - public void ExplicitReturnType_42() + public void Async_05() { - string source = "static async ref int () => default"; + string source = "@async () => default"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); { - N(SyntaxKind.StaticKeyword); - N(SyntaxKind.AsyncKeyword); - N(SyntaxKind.RefType); + N(SyntaxKind.IdentifierName); { - N(SyntaxKind.RefKeyword); - N(SyntaxKind.PredefinedType); - { - N(SyntaxKind.IntKeyword); - } + N(SyntaxKind.IdentifierToken, "@async"); } N(SyntaxKind.ParameterList); { @@ -1677,7 +2979,7 @@ public void ExplicitReturnType_42() } [Fact] - public void ExplicitReturnType_43() + public void Async_06() { string source = "async async (async async) => async"; UsingExpression(source); @@ -1708,10 +3010,11 @@ public void ExplicitReturnType_43() EOF(); } - [Fact] - public void ExplicitReturnType_44() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void Attributes_01(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "[A] void () => { }"; + string source = $"[A] {modifiers} void () => {{ }}"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); @@ -1728,6 +3031,10 @@ public void ExplicitReturnType_44() } N(SyntaxKind.CloseBracketToken); } + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); @@ -1748,7 +3055,7 @@ public void ExplicitReturnType_44() } [Fact] - public void ExplicitReturnType_45() + public void Attributes_02() { string source = "[A][B] T () => default"; UsingExpression(source); @@ -1797,10 +3104,11 @@ public void ExplicitReturnType_45() EOF(); } - [Fact] - public void ExplicitReturnType_46() + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void Attributes_03(string modifiers, params SyntaxKind[] modifierKinds) { - string source = "[A, B] ref T () => default"; + string source = $"[A, B] {modifiers} ref T () => default"; UsingExpression(source); N(SyntaxKind.ParenthesizedLambdaExpression); @@ -1825,6 +3133,10 @@ public void ExplicitReturnType_46() } N(SyntaxKind.CloseBracketToken); } + foreach (var modifier in modifierKinds) + { + N(modifier); + } N(SyntaxKind.RefType); { N(SyntaxKind.RefKeyword); @@ -1846,5 +3158,240 @@ public void ExplicitReturnType_46() } EOF(); } + + [MemberData(nameof(AsyncAndStaticModifiers))] + [Theory] + public void AttributeArgument_01(string modifiers, params SyntaxKind[] modifierKinds) + { + string source = $"[A({modifiers} void () => {{ }})] class C {{ }}"; + UsingDeclaration(source); + + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.AttributeArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.AttributeArgument); + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + foreach (var modifier in modifierKinds) + { + N(modifier); + } + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact] + public void AttributeArgument_02() + { + string source = "[A(T () => default)] class C { }"; + UsingDeclaration(source); + + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.AttributeArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.AttributeArgument); + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact] + public void AttributeArgument_03() + { + string source = "[A(delegate* () => default)] class C { }"; + UsingDeclaration(source); + + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.AttributeArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.AttributeArgument); + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact] + public void AttributeArgument_04() + { + string source = "[A(ref int () => default)] class C { }"; + UsingDeclaration(source); + + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "A"); + } + N(SyntaxKind.AttributeArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.AttributeArgument); + { + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + } + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs index 1b4d061c55428..6932b167ff190 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs @@ -1343,33 +1343,30 @@ class c N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { - N(SyntaxKind.InvocationExpression); + N(SyntaxKind.ParenthesizedLambdaExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "await"); } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } - } - M(SyntaxKind.SemicolonToken); - } - N(SyntaxKind.ExpressionStatement); - { - N(SyntaxKind.ObjectCreationExpression); - { - N(SyntaxKind.NewKeyword); - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "await"); - } - N(SyntaxKind.ArgumentList); + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.ObjectCreationExpression); { - N(SyntaxKind.OpenParenToken); - N(SyntaxKind.CloseParenToken); + N(SyntaxKind.NewKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "await"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } } } N(SyntaxKind.SemicolonToken); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs index 5d7a065b1833b..93d5b99c954fb 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs @@ -6058,31 +6058,25 @@ public void Ternary_Expression34() N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.QuestionToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.InvocationExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "m"); } - N(SyntaxKind.ParameterList); + N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); + N(SyntaxKind.Argument); { N(SyntaxKind.OutKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "c"); } - M(SyntaxKind.IdentifierToken); } M(SyntaxKind.CloseParenToken); } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } } M(SyntaxKind.ColonToken); M(SyntaxKind.IdentifierName); @@ -6115,31 +6109,25 @@ public void Ternary_Expression35() N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.QuestionToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.InvocationExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "m"); } - N(SyntaxKind.ParameterList); + N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); + N(SyntaxKind.Argument); { N(SyntaxKind.RefKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "c"); } - M(SyntaxKind.IdentifierToken); } M(SyntaxKind.CloseParenToken); } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } } M(SyntaxKind.ColonToken); M(SyntaxKind.IdentifierName); @@ -7000,36 +6988,33 @@ public void Ternary_Expression49() N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.QuestionToken); - N(SyntaxKind.ParenthesizedLambdaExpression); + N(SyntaxKind.InvocationExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "a"); } - N(SyntaxKind.ParameterList); + N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); - N(SyntaxKind.Parameter); + N(SyntaxKind.Argument); { N(SyntaxKind.RefKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "a"); } - M(SyntaxKind.IdentifierToken); } N(SyntaxKind.CommaToken); - M(SyntaxKind.Parameter); + M(SyntaxKind.Argument); { - M(SyntaxKind.IdentifierToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } } M(SyntaxKind.CloseParenToken); } - M(SyntaxKind.EqualsGreaterThanToken); - M(SyntaxKind.IdentifierName); - { - M(SyntaxKind.IdentifierToken); - } } M(SyntaxKind.ColonToken); M(SyntaxKind.IdentifierName); From 52dbe075a6fb4990061803d19194da6127150f77 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Mon, 7 Jun 2021 22:04:38 -0700 Subject: [PATCH 3/6] Update public API --- src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 780fce023cde3..0bb3668b58f52 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -5,10 +5,14 @@ abstract Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax.AttributeLi Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.AddAttributeLists(params Microsoft.CodeAnalysis.CSharp.Syntax.AttributeListSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax override Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.AttributeLists.get -> Microsoft.CodeAnalysis.SyntaxList +Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.ReturnType.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.WithAttributeLists(Microsoft.CodeAnalysis.SyntaxList attributeLists) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.WithReturnType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax -static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax +static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.WithClassOrStructKeyword(Microsoft.CodeAnalysis.SyntaxToken classOrStructKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.SyntaxToken classOrStructKeyword, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BaseListSyntax baseList, Microsoft.CodeAnalysis.SyntaxList constraintClauses, Microsoft.CodeAnalysis.SyntaxToken openBraceToken, Microsoft.CodeAnalysis.SyntaxList members, Microsoft.CodeAnalysis.SyntaxToken closeBraceToken, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RecordDeclaration(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.RecordDeclarationSyntax From 0dd54f580d4b836411b1f55e4739c185d4b6a543 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Tue, 8 Jun 2021 10:13:54 -0700 Subject: [PATCH 4/6] PR feedback --- .../CSharp/Portable/Parser/LanguageParser.cs | 16 +- .../Parsing/LambdaReturnTypeParsingTests.cs | 219 +++++++++++++++++- 2 files changed, 224 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 751f0371a0791..38a0a2b61f714 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -10466,7 +10466,14 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) case SyntaxKind.InterpolatedStringToken: return this.ParseInterpolatedStringToken(); case SyntaxKind.OpenParenToken: - return this.ParseCastOrParenExpressionOrLambdaOrTuple(precedence); + if (IsPossibleLambdaExpression(precedence)) + { + if (this.TryParseLambdaExpression() is { } lambda) + { + return lambda; + } + } + return this.ParseCastOrParenExpressionOrTuple(); case SyntaxKind.NewKeyword: return this.ParseNewExpression(); case SyntaxKind.StackAllocKeyword: @@ -11223,15 +11230,10 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) } } - private ExpressionSyntax ParseCastOrParenExpressionOrLambdaOrTuple(Precedence precedence) + private ExpressionSyntax ParseCastOrParenExpressionOrTuple() { Debug.Assert(this.CurrentToken.Kind == SyntaxKind.OpenParenToken); - if (IsPossibleLambdaExpression(precedence) && this.TryParseLambdaExpression() is { } lambda) - { - return lambda; - } - var resetPoint = this.GetResetPoint(); try { diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs index 56d4a56455e64..7bb4d6a2063d9 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs @@ -221,6 +221,66 @@ void verify() } } + [Fact] + public void AnonymousMethod_01() + { + string source = "delegate T { return default; }"; + verify(source, TestOptions.Regular9); + verify(source, TestOptions.RegularPreview); + + void verify(string source, CSharpParseOptions parseOptions) + { + UsingExpression(source, parseOptions, + // (1,1): error CS1073: Unexpected token 'T' + // delegate T { return default; } + Diagnostic(ErrorCode.ERR_UnexpectedToken, "delegate ").WithArguments("T").WithLocation(1, 1), + // (1,10): error CS1514: { expected + // delegate T { return default; } + Diagnostic(ErrorCode.ERR_LbraceExpected, "T").WithLocation(1, 10)); + + N(SyntaxKind.AnonymousMethodExpression); + { + N(SyntaxKind.DelegateKeyword); + M(SyntaxKind.Block); + { + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + } + + [Fact] + public void AnonymousMethod_02() + { + string source = "delegate int (int x) { return x; }"; + verify(source, TestOptions.Regular9); + verify(source, TestOptions.RegularPreview); + + void verify(string source, CSharpParseOptions parseOptions) + { + UsingExpression(source, parseOptions, + // (1,1): error CS1073: Unexpected token 'int' + // delegate int (int x) { return x; } + Diagnostic(ErrorCode.ERR_UnexpectedToken, "delegate ").WithArguments("int").WithLocation(1, 1), + // (1,10): error CS1514: { expected + // delegate int (int x) { return x; } + Diagnostic(ErrorCode.ERR_LbraceExpected, "int").WithLocation(1, 10)); + + N(SyntaxKind.AnonymousMethodExpression); + { + N(SyntaxKind.DelegateKeyword); + M(SyntaxKind.Block); + { + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + } + [MemberData(nameof(AsyncAndStaticModifiers))] [Theory] public void PrimitiveReturnType_01(string modifiers, params SyntaxKind[] modifierKinds) @@ -428,7 +488,7 @@ public void PointerReturnType_03() [MemberData(nameof(AsyncAndStaticModifiers))] [Theory] - public void FunctionPointerReturnType(string modifiers, params SyntaxKind[] modifierKinds) + public void FunctionPointerReturnType_01(string modifiers, params SyntaxKind[] modifierKinds) { string source = modifiers + " delegate* () => default"; UsingExpression(source); @@ -470,6 +530,80 @@ public void FunctionPointerReturnType(string modifiers, params SyntaxKind[] modi EOF(); } + [Fact] + public void FunctionPointerReturnType_02() + { + string source = "delegate* unmanaged[Cdecl], void> () => default"; + UsingExpression(source); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerCallingConvention); + { + N(SyntaxKind.UnmanagedKeyword); + N(SyntaxKind.FunctionPointerUnmanagedCallingConventionList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.FunctionPointerUnmanagedCallingConvention); + { + N(SyntaxKind.IdentifierToken, "Cdecl"); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.RefKeyword); + N(SyntaxKind.FunctionPointerType); + { + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.DefaultLiteralExpression); + { + N(SyntaxKind.DefaultKeyword); + } + } + EOF(); + } + [Fact] public void NullableReturnTypeOrConditional_01A() { @@ -2612,6 +2746,83 @@ public void InvocationOrLambda_07() [Fact] public void InvocationOrLambda_08() + { + string source = "F(a, b) =>"; + UsingExpression(source, + // (1,11): error CS1733: Expected expression + // F(a, b) => + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 11)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void InvocationOrLambda_09() + { + string source = "F(a, b) => {"; + UsingExpression(source, + // (1,13): error CS1513: } expected + // F(a, b) => { + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(1, 13)); + + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "F"); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "a"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.IdentifierToken, "b"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + } + EOF(); + } + + [Fact] + public void InvocationOrLambda_10() { string source = "F(a, b) => { }"; UsingExpression(source); @@ -2647,7 +2858,7 @@ public void InvocationOrLambda_08() } [Fact] - public void InvocationOrLambda_09() + public void InvocationOrLambda_11() { string source = "F(ref a, out b, in c) => { }"; UsingExpression(source, @@ -2712,7 +2923,7 @@ public void InvocationOrLambda_09() } [Fact] - public void InvocationOrLambda_10() + public void InvocationOrLambda_12() { string source = "F(A a, B b) => { }"; UsingExpression(source); @@ -2756,7 +2967,7 @@ public void InvocationOrLambda_10() } [Fact] - public void InvocationOrLambda_11() + public void InvocationOrLambda_13() { string source = "F(ref A a, out B b, in C c) => { }"; UsingExpression(source); From 2e733acc06b2aab5aa7fad23aee9ea6d3caed0d8 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Tue, 8 Jun 2021 21:57:10 -0700 Subject: [PATCH 5/6] PR feedback --- .../Parsing/LambdaReturnTypeParsingTests.cs | 419 ++++++++++++++++-- 1 file changed, 390 insertions(+), 29 deletions(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs index 7bb4d6a2063d9..ea9c6d38bf71d 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/LambdaReturnTypeParsingTests.cs @@ -221,6 +221,57 @@ void verify() } } + [Fact] + public void NamedLambda_01() + { + string source = "T F() => default"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token 'F' + // T F() => default + Diagnostic(ErrorCode.ERR_UnexpectedToken, "T").WithArguments("F").WithLocation(1, 1)); + + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + EOF(); + } + + [Fact] + public void NamedLambda_02() + { + string source = "async T F() => { }"; + UsingExpression(source, + // (1,1): error CS1073: Unexpected token 'T' + // async T F() => { } + Diagnostic(ErrorCode.ERR_UnexpectedToken, "async").WithArguments("T").WithLocation(1, 1)); + + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "async"); + } + EOF(); + } + + [Fact] + public void NamedLambda_03() + { + string source = "static T F(int x) => { }"; + UsingExpression(source, + // (1,1): error CS1525: Invalid expression term 'static' + // static T F(int x) => { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "static").WithArguments("static").WithLocation(1, 1), + // (1,1): error CS1073: Unexpected token 'static' + // static T F(int x) => { } + Diagnostic(ErrorCode.ERR_UnexpectedToken, "").WithArguments("static").WithLocation(1, 1)); + + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + EOF(); + } + [Fact] public void AnonymousMethod_01() { @@ -605,7 +656,7 @@ public void FunctionPointerReturnType_02() } [Fact] - public void NullableReturnTypeOrConditional_01A() + public void NullableReturnTypeOrConditional_01() { string source = "int? () => null"; UsingExpression(source); @@ -635,7 +686,7 @@ public void NullableReturnTypeOrConditional_01A() } [Fact] - public void NullableReturnTypeOrConditional_01B() + public void NullableReturnTypeOrConditional_02() { string source = "int? () => x : y"; UsingExpression(source, @@ -668,7 +719,7 @@ public void NullableReturnTypeOrConditional_01B() } [Fact] - public void NullableReturnTypeOrConditional_02A() + public void NullableReturnTypeOrConditional_03() { string source = "int[]? () => null"; UsingExpression(source); @@ -710,7 +761,7 @@ public void NullableReturnTypeOrConditional_02A() } [Fact] - public void NullableReturnTypeOrConditional_02B() + public void NullableReturnTypeOrConditional_04() { string source = "int[]? () => x : y"; UsingExpression(source, @@ -755,7 +806,7 @@ public void NullableReturnTypeOrConditional_02B() } [Fact] - public void NullableReturnTypeOrConditional_03A() + public void NullableReturnTypeOrConditional_05() { string source = "int.MaxValue? () => null"; UsingExpression(source, @@ -804,7 +855,7 @@ public void NullableReturnTypeOrConditional_03A() } [Fact] - public void NullableReturnTypeOrConditional_03B() + public void NullableReturnTypeOrConditional_06() { string source = "int.MaxValue? () => x : y"; UsingExpression(source); @@ -847,7 +898,7 @@ public void NullableReturnTypeOrConditional_03B() } [Fact] - public void NullableReturnTypeOrConditional_04A() + public void NullableReturnTypeOrConditional_07() { string source = "T? () => x"; UsingExpression(source); @@ -877,7 +928,7 @@ public void NullableReturnTypeOrConditional_04A() } [Fact] - public void NullableReturnTypeOrConditional_04B() + public void NullableReturnTypeOrConditional_08() { string source = "T? () => x : y"; UsingExpression(source); @@ -912,7 +963,7 @@ public void NullableReturnTypeOrConditional_04B() } [Fact] - public void NullableReturnTypeOrConditional_05A() + public void NullableReturnTypeOrConditional_09() { string source = "(x, y)? () => x"; UsingExpression(source); @@ -958,7 +1009,7 @@ public void NullableReturnTypeOrConditional_05A() } [Fact] - public void NullableReturnTypeOrConditional_05B() + public void NullableReturnTypeOrConditional_10() { string source = "(x, y)? () => x : z"; UsingExpression(source); @@ -1009,7 +1060,7 @@ public void NullableReturnTypeOrConditional_05B() } [Fact] - public void NullableReturnTypeOrConditional_06A() + public void NullableReturnTypeOrConditional_11() { string source = "T[]? () => x"; UsingExpression(source); @@ -1051,7 +1102,7 @@ public void NullableReturnTypeOrConditional_06A() } [Fact] - public void NullableReturnTypeOrConditional_06B() + public void NullableReturnTypeOrConditional_12() { string source = "T[]? () => x : y"; UsingExpression(source, @@ -1104,7 +1155,113 @@ public void NullableReturnTypeOrConditional_06B() } [Fact] - public void NullableReturnTypeOrConditional_07A() + public void NullableReturnTypeOrConditional_13() + { + string source = "T[0]? () => x"; + UsingExpression(source, + // (1,14): error CS1003: Syntax error, ':' expected + // T[0]? () => x + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":", "").WithLocation(1, 14), + // (1,14): error CS1733: Expected expression + // T[0]? () => x + Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 14)); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + M(SyntaxKind.ColonToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_14() + { + string source = "T[0]? () => x : y"; + UsingExpression(source); + + N(SyntaxKind.ConditionalExpression); + { + N(SyntaxKind.ElementAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.BracketedArgumentList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.QuestionToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.ColonToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + EOF(); + } + + [Fact] + public void NullableReturnTypeOrConditional_15() { string source = "A? () => x"; UsingExpression(source); @@ -1143,7 +1300,7 @@ public void NullableReturnTypeOrConditional_07A() } [Fact] - public void NullableReturnTypeOrConditional_07B() + public void NullableReturnTypeOrConditional_16() { string source = "A? () => x : y"; UsingExpression(source); @@ -1187,7 +1344,7 @@ public void NullableReturnTypeOrConditional_07B() } [Fact] - public void NullableReturnTypeOrConditional_08A() + public void NullableReturnTypeOrConditional_17() { string source = "int*? () => x"; UsingExpression(source, @@ -1242,7 +1399,7 @@ public void NullableReturnTypeOrConditional_08A() } [Fact] - public void NullableReturnTypeOrConditional_08B() + public void NullableReturnTypeOrConditional_18() { string source = "int*? () => x : y"; UsingExpression(source, @@ -1291,7 +1448,7 @@ public void NullableReturnTypeOrConditional_08B() } [Fact] - public void NullableReturnTypeOrConditional_09A() + public void NullableReturnTypeOrConditional_19() { string source = "delegate*? () => x"; UsingExpression(source, @@ -1376,7 +1533,7 @@ public void NullableReturnTypeOrConditional_09A() } [Fact] - public void NullableReturnTypeOrConditional_09B() + public void NullableReturnTypeOrConditional_20() { string source = "delegate*? () => x : y"; UsingExpression(source, @@ -1455,7 +1612,7 @@ public void NullableReturnTypeOrConditional_09B() } [Fact] - public void NullableReturnTypeOrConditional_10A() + public void NullableReturnTypeOrConditional_21() { string source = "static T? () => x"; UsingExpression(source); @@ -1486,7 +1643,7 @@ public void NullableReturnTypeOrConditional_10A() } [Fact] - public void NullableReturnTypeOrConditional_10B() + public void NullableReturnTypeOrConditional_22() { string source = "static T? () => x : y"; UsingExpression(source, @@ -1520,7 +1677,7 @@ public void NullableReturnTypeOrConditional_10B() } [Fact] - public void NullableReturnTypeOrConditional_11A() + public void NullableReturnTypeOrConditional_23() { string source = "async? () => x"; UsingExpression(source); @@ -1550,7 +1707,7 @@ public void NullableReturnTypeOrConditional_11A() } [Fact] - public void NullableReturnTypeOrConditional_11B() + public void NullableReturnTypeOrConditional_24() { string source = "async? () => x : y"; UsingExpression(source); @@ -1585,7 +1742,7 @@ public void NullableReturnTypeOrConditional_11B() } [Fact] - public void NullableReturnTypeOrConditional_12A() + public void NullableReturnTypeOrConditional_25() { string source = "async T? () => x"; UsingExpression(source); @@ -1616,7 +1773,7 @@ public void NullableReturnTypeOrConditional_12A() } [Fact] - public void NullableReturnTypeOrConditional_12B() + public void NullableReturnTypeOrConditional_26() { string source = "async T? () => x : y"; UsingExpression(source, @@ -1632,7 +1789,7 @@ public void NullableReturnTypeOrConditional_12B() } [Fact] - public void NullableReturnTypeOrConditional_13A() + public void NullableReturnTypeOrConditional_27() { string source = "[A] T? () => x"; UsingExpression(source); @@ -1674,7 +1831,7 @@ public void NullableReturnTypeOrConditional_13A() } [Fact] - public void NullableReturnTypeOrConditional_13B() + public void NullableReturnTypeOrConditional_28() { string source = "[A] T? () => x : y"; UsingExpression(source, @@ -1719,7 +1876,7 @@ public void NullableReturnTypeOrConditional_13B() } [Fact] - public void NullableReturnTypeOrConditional_14A() + public void NullableReturnTypeOrConditional_29() { string source = "b? c? () => x : y"; UsingExpression(source, @@ -1773,7 +1930,7 @@ public void NullableReturnTypeOrConditional_14A() } [Fact] - public void NullableReturnTypeOrConditional_14B() + public void NullableReturnTypeOrConditional_30() { string source = "b? c? () => x : y : z"; UsingExpression(source); @@ -1821,7 +1978,7 @@ public void NullableReturnTypeOrConditional_14B() } [Fact] - public void NullableReturnTypeOrConditional_14C() + public void NullableReturnTypeOrConditional_31() { string source = "b? (c? () => x) : y"; UsingExpression(source); @@ -3022,6 +3179,210 @@ public void InvocationOrLambda_13() EOF(); } + [Fact] + public void SwitchExpression_01() + { + string source = "x switch { int () => 0 => 1 }"; + UsingExpression(source, + // (1,24): error CS1003: Syntax error, ',' expected + // x switch { int () => 0 => 1 } + Diagnostic(ErrorCode.ERR_SyntaxError, "=>").WithArguments(",", "=>").WithLocation(1, 24), + // (1,24): error CS8504: Pattern missing + // x switch { int () => 0 => 1 } + Diagnostic(ErrorCode.ERR_MissingPattern, "=>").WithLocation(1, 24)); + + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.PositionalPatternClause); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "0"); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact] + public void SwitchExpression_02() + { + string source = "x switch { T () => { } => 1 }"; + UsingExpression(source, + // (1,20): error CS1525: Invalid expression term '{' + // x switch { T () => { } => 1 } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "{").WithArguments("{").WithLocation(1, 20), + // (1,20): error CS1003: Syntax error, ',' expected + // x switch { T () => { } => 1 } + Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments(",", "{").WithLocation(1, 20)); + + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.PositionalPatternClause); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.SwitchExpressionArm); + { + N(SyntaxKind.RecursivePattern); + { + N(SyntaxKind.PropertyPatternClause); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + + [Fact] + public void SwitchExpression_03() + { + string source = "x switch { static T? () => { } => 1 }"; + UsingExpression(source, + // (1,12): error CS1525: Invalid expression term 'static' + // x switch { static T? () => { } => 1 } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "static").WithArguments("static").WithLocation(1, 12), + // (1,12): error CS1003: Syntax error, '=>' expected + // x switch { static T? () => { } => 1 } + Diagnostic(ErrorCode.ERR_SyntaxError, "static").WithArguments("=>", "static").WithLocation(1, 12), + // (1,32): error CS1003: Syntax error, ',' expected + // x switch { static T? () => { } => 1 } + Diagnostic(ErrorCode.ERR_SyntaxError, "=>").WithArguments(",", "=>").WithLocation(1, 32), + // (1,32): error CS8504: Pattern missing + // x switch { static T? () => { } => 1 } + Diagnostic(ErrorCode.ERR_MissingPattern, "=>").WithLocation(1, 32)); + + N(SyntaxKind.SwitchExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.SwitchKeyword); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.ParenthesizedLambdaExpression); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.NullableType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "T"); + } + N(SyntaxKind.QuestionToken); + } + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + M(SyntaxKind.CommaToken); + N(SyntaxKind.SwitchExpressionArm); + { + M(SyntaxKind.ConstantPattern); + { + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + N(SyntaxKind.EqualsGreaterThanToken); + N(SyntaxKind.NumericLiteralExpression); + { + N(SyntaxKind.NumericLiteralToken, "1"); + } + } + N(SyntaxKind.CloseBraceToken); + } + EOF(); + } + [Fact] public void Async_01() { From 581369497376f23bb83fe03da8271b92f8f07cbb Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Wed, 9 Jun 2021 13:10:39 -0700 Subject: [PATCH 6/6] PR feedback --- .../CSharp/Portable/Parser/LanguageParser.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 38a0a2b61f714..a7eb7e40d7f85 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -10486,6 +10486,7 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) } return this.ParseAnonymousMethodExpression(); case SyntaxKind.RefKeyword: + // check for lambda expression with explicit ref return type: `ref int () => { ... }` if (this.IsPossibleLambdaExpression(precedence)) { return this.ParseLambdaExpression(); @@ -10493,7 +10494,6 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) // ref is not expected to appear in this position. return this.AddError(ParsePossibleRefExpression(), ErrorCode.ERR_InvalidExprTerm, SyntaxFacts.GetText(tk)); default: - // check for intrinsic type followed by '.' if (IsPredefinedType(tk)) { if (this.IsPossibleLambdaExpression(precedence)) @@ -10501,6 +10501,7 @@ private ExpressionSyntax ParseTermWithoutPostfix(Precedence precedence) return this.ParseLambdaExpression(); } + // check for intrinsic type followed by '.' var expr = _syntaxFactory.PredefinedType(this.EatToken()); if (this.CurrentToken.Kind != SyntaxKind.DotToken || tk == SyntaxKind.VoidKeyword) @@ -11165,13 +11166,15 @@ private bool ScanExplicitlyTypedLambda(Precedence precedence) var resetPoint = this.GetResetPoint(); try { - // do we have the following, possibly with attributes before the parameter: - // case 1: ( T x [, ...]) => - // case 2: ( out T x [, ...]) => - // case 3: ( ref T x [, ...]) => - // case 4: ( in T x [, ...]) => + // Do we have the following, where the attributes, modifier, and type are + // optional? If so then parse it as a lambda. + // (attributes modifier T x [, ...]) => // - // if so then parse it as a lambda + // It's not sufficient to assume this is a lambda expression if we see a + // modifier such as `(ref x,` because the caller of this method may have + // scanned past a preceding identifier, and `F (ref x,` might be a call to + // method F rather than a lambda expression with return type F. + // Instead, we need to scan to `=>`. while (true) {