From 42b2886d6e92dd0aacf7b20210205f146d5ec07e Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 14 Apr 2015 15:40:03 -0700 Subject: [PATCH] Adjust implementation of LookupPosition.IsInMethodDeclaration to consider an expression body even in presence of a block. Fixed #1702. --- .../CSharp/Portable/Syntax/LookupPosition.cs | 9 +- .../Semantics/ExpressionBodiedMemberTests.cs | 349 ++++++++++++++++++ 2 files changed, 356 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs index 8e85bc13af7..345c50bab54 100644 --- a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs +++ b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs @@ -121,8 +121,13 @@ internal static bool IsInMethodDeclaration(int position, BaseMethodDeclarationSy Debug.Assert(methodDecl != null); var body = methodDecl.Body; - SyntaxToken lastToken = body == null ? methodDecl.SemicolonToken : body.CloseBraceToken; - return IsBeforeToken(position, methodDecl, lastToken); + if (body == null) + { + return IsBeforeToken(position, methodDecl, methodDecl.SemicolonToken); + } + + return IsBeforeToken(position, methodDecl, body.CloseBraceToken) || + IsInExpressionBody(position, methodDecl.GetExpressionBodySyntax(), methodDecl.SemicolonToken); } internal static bool IsInMethodDeclaration(int position, AccessorDeclarationSyntax accessorDecl) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ExpressionBodiedMemberTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ExpressionBodiedMemberTests.cs index 681b8ece993..39022c89f08 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ExpressionBodiedMemberTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ExpressionBodiedMemberTests.cs @@ -382,5 +382,354 @@ class Program // private void M() => (new object()); Diagnostic(ErrorCode.ERR_IllegalStatement, "(new object())").WithLocation(4, 25)); } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_01() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static void M1() + { } + => P1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8057: Methods cannot combine block bodies with expression bodies. + // static void M1() + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"static void M1() + { } + => P1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_02() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public int operator + (C x, C y) + { return 1; } + => P1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8057: Methods cannot combine block bodies with expression bodies. + // static public int operator + (C x, C y) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"static public int operator + (C x, C y) + { return 1; } + => P1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_03() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + C() + { } + => P1; +} +"); + + comp.VerifyDiagnostics( + // (8,5): error CS1519: Invalid token '=>' in class, struct, or interface member declaration + // => P1; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=>").WithArguments("=>").WithLocation(8, 5), + // (8,10): error CS1519: Invalid token ';' in class, struct, or interface member declaration + // => P1; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(8, 10), + // (8,10): error CS1519: Invalid token ';' in class, struct, or interface member declaration + // => P1; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(8, 10) + ); + + var tree = comp.SyntaxTrees[0]; + Assert.False(tree.GetRoot().DescendantNodes().OfType().Any()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_04() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + ~C() + { } + => P1; +} +"); + + comp.VerifyDiagnostics( + // (8,5): error CS1519: Invalid token '=>' in class, struct, or interface member declaration + // => P1; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=>").WithArguments("=>").WithLocation(8, 5), + // (8,10): error CS1519: Invalid token ';' in class, struct, or interface member declaration + // => P1; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(8, 10), + // (8,10): error CS1519: Invalid token ';' in class, struct, or interface member declaration + // => P1; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(8, 10) + ); + + var tree = comp.SyntaxTrees[0]; + Assert.False(tree.GetRoot().DescendantNodes().OfType().Any()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_05() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public int P2 + { + get + { return 1; } + => P1; + } +} +"); + + comp.VerifyDiagnostics( + // (10,9): error CS1014: A get or set accessor expected + // => P1; + Diagnostic(ErrorCode.ERR_GetOrSetExpected, "=>").WithLocation(10, 9), + // (10,12): error CS1014: A get or set accessor expected + // => P1; + Diagnostic(ErrorCode.ERR_GetOrSetExpected, "P1").WithLocation(10, 12) + ); + + var tree = comp.SyntaxTrees[0]; + Assert.False(tree.GetRoot().DescendantNodes().OfType().Any()); + } + + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_06() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public int P2 + { + } + => P1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8056: Properties cannot combine accessor lists with expression bodies. + // static public int P2 + Diagnostic(ErrorCode.ERR_AccessorListAndExpressionBody, @"static public int P2 + { + } + => P1;").WithLocation(6, 5), + // (6,23): error CS0548: 'C.P2': property or indexer must have at least one accessor + // static public int P2 + Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P2").WithArguments("C.P2").WithLocation(6, 23) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Null(model.GetSymbolInfo(node).Symbol); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_07() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public explicit operator int (C x) + { return 1; } + => P1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8057: Methods cannot combine block bodies with expression bodies. + // static public explicit operator int (C x) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"static public explicit operator int (C x) + { return 1; } + => P1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_08() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static int M1() + { return P1; } + => 1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8057: Methods cannot combine block bodies with expression bodies. + // static int M1() + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"static int M1() + { return P1; } + => 1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_09() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public int operator + (C x, C y) + { return P1; } + => 1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8057: Methods cannot combine block bodies with expression bodies. + // static public int operator + (C x, C y) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"static public int operator + (C x, C y) + { return P1; } + => 1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_10() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public int P2 + { + get { return P1; } + } + => 1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8056: Properties cannot combine accessor lists with expression bodies. + // static public int P2 + Diagnostic(ErrorCode.ERR_AccessorListAndExpressionBody, @"static public int P2 + { + get { return P1; } + } + => 1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(1702, "https://github.com/dotnet/roslyn/issues/1702")] + public void BlockBodyAndExpressionBody_11() + { + var comp = CreateCompilationWithMscorlib(@" +public class C +{ + static int P1 {get; set;} + + static public explicit operator int (C x) + { return P1; } + => 1; +} +"); + + comp.VerifyDiagnostics( + // (6,5): error CS8057: Methods cannot combine block bodies with expression bodies. + // static public explicit operator int (C x) + Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, @"static public explicit operator int (C x) + { return P1; } + => 1;").WithLocation(6, 5) + ); + + var tree = comp.SyntaxTrees[0]; + var model = comp.GetSemanticModel(tree); + + var node = tree.GetRoot().DescendantNodes().OfType().Single().Expression; + + Assert.Equal("P1", node.ToString()); + Assert.Equal("System.Int32 C.P1 { get; set; }", model.GetSymbolInfo(node).Symbol.ToTestDisplayString()); + } + } } -- GitLab