diff --git a/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs b/src/Compilers/CSharp/Portable/Syntax/LookupPosition.cs index 8e85bc13af738c5aa3356322595882edab4bad0d..345c50bab54dab889d9ea0da2eaea79d741d09a3 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 681b8ece993fdb4bd28826593a9ff45adaad408f..39022c89f08b3962c3581da43149dd7c2b1732b0 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()); + } + } }