From d3de5b2bf31b1e02710417b2924e1072d72b237c Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 5 Jan 2018 11:48:50 -0800 Subject: [PATCH] MemberSemanticModel.GetBoundLambdaOrQuery should use GetAdjustedNodePosition helper to ensure proper handling of zero-length tokens at the beginning of a syntax node. (#24049) Fixes #23883. --- .../Compilation/MemberSemanticModel.cs | 8 +- .../Test/Semantic/Semantics/LambdaTests.cs | 79 +++++++++++++++++++ .../QuickInfo/SemanticQuickInfoSourceTests.cs | 39 +++++++++ 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 0e48d8c3efa..aa8c49b2da1 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -1469,7 +1469,7 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) if (enclosingLambdaOrQuery == null) { nodeToBind = bindingRoot; - lambdaRecoveryBinder = GetEnclosingBinderInternalWithinRoot(nodeToBind, nodeToBind.SpanStart); + lambdaRecoveryBinder = GetEnclosingBinderInternalWithinRoot(nodeToBind, GetAdjustedNodePosition(nodeToBind)); } else { @@ -1497,7 +1497,7 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) return GetLowerBoundNode(nodes); } - lambdaRecoveryBinder = GetEnclosingBinderInLambdaOrQuery(nodeToBind.SpanStart, nodeToBind, enclosingLambdaOrQuery, ref boundEnclosingLambdaOrQuery); + lambdaRecoveryBinder = GetEnclosingBinderInLambdaOrQuery(GetAdjustedNodePosition(nodeToBind), nodeToBind, enclosingLambdaOrQuery, ref boundEnclosingLambdaOrQuery); } Binder incrementalBinder = new IncrementalBinder(this, lambdaRecoveryBinder); @@ -1521,11 +1521,11 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery) // situations. Let's bind the node directly. if (enclosingLambdaOrQuery == null) { - lambdaRecoveryBinder = GetEnclosingBinderInternalWithinRoot(lambdaOrQuery, lambdaOrQuery.SpanStart); + lambdaRecoveryBinder = GetEnclosingBinderInternalWithinRoot(lambdaOrQuery, GetAdjustedNodePosition(lambdaOrQuery)); } else { - lambdaRecoveryBinder = GetEnclosingBinderInLambdaOrQuery(lambdaOrQuery.SpanStart, lambdaOrQuery, enclosingLambdaOrQuery, ref boundEnclosingLambdaOrQuery); + lambdaRecoveryBinder = GetEnclosingBinderInLambdaOrQuery(GetAdjustedNodePosition(lambdaOrQuery), lambdaOrQuery, enclosingLambdaOrQuery, ref boundEnclosingLambdaOrQuery); } incrementalBinder = new IncrementalBinder(this, lambdaRecoveryBinder); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index cc67784cd50..6a7ccf522f9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -2630,5 +2630,84 @@ public static void Main() var comp = CreateCompilationWithMscorlibAndSystemCore(src, options: TestOptions.DebugExe); CompileAndVerify(comp, expectedOutput: "1234"); } + + [Fact, WorkItem(23883, "https://github.com/dotnet/roslyn/issues/23883")] + public void InMalformedEmbeddedStatement_01() + { + var source = @" +class Program +{ + void method1() + { + if (method2()) + .Any(b => b.ContentType, out var chars) + { + } + } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var comp = CreateStandardCompilation(tree); + + ExpressionSyntax contentType = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "ContentType").Single(); + + var model = comp.GetSemanticModel(tree); + Assert.Equal("ContentType", contentType.ToString()); + Assert.Null(model.GetSymbolInfo(contentType).Symbol); + Assert.Equal(TypeKind.Error, model.GetTypeInfo(contentType).Type.TypeKind); + + ExpressionSyntax b = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "b").Single(); + + model = comp.GetSemanticModel(tree); + Assert.Equal("b", b.ToString()); + ISymbol symbol = model.GetSymbolInfo(b).Symbol; + Assert.Equal(SymbolKind.Parameter, symbol.Kind); + Assert.Equal("? b", symbol.ToTestDisplayString()); + Assert.Equal(TypeKind.Error, model.GetTypeInfo(b).Type.TypeKind); + + ParameterSyntax parameterSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single(); + + model = comp.GetSemanticModel(tree); + symbol = model.GetDeclaredSymbol(parameterSyntax); + Assert.Equal(SymbolKind.Parameter, symbol.Kind); + Assert.Equal("? b", symbol.ToTestDisplayString()); + } + + [Fact, WorkItem(23883, "https://github.com/dotnet/roslyn/issues/23883")] + public void InMalformedEmbeddedStatement_02() + { + var source = @" +class Program +{ + void method1() + { + if (method2()) + .Any(b => b.ContentType, out var chars) + { + } + } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(source); + var comp = CreateStandardCompilation(tree); + + ExpressionSyntax contentType = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "ContentType").Single(); + + var model = comp.GetSemanticModel(tree); + Assert.Equal("ContentType", contentType.ToString()); + var lambda = (MethodSymbol)model.GetEnclosingSymbol(contentType.SpanStart); + Assert.Equal(MethodKind.AnonymousFunction, lambda.MethodKind); + + ExpressionSyntax b = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "b").Single(); + + model = comp.GetSemanticModel(tree); + Assert.Equal("b", b.ToString()); + lambda = (MethodSymbol)model.GetEnclosingSymbol(b.SpanStart); + Assert.Equal(MethodKind.AnonymousFunction, lambda.MethodKind); + + model = comp.GetSemanticModel(tree); + ParameterSyntax parameterSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Single(); + Assert.Equal("void Program.method1()", model.GetEnclosingSymbol(parameterSyntax.SpanStart).ToTestDisplayString()); + } } } diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index 2000e4c3c57..78cdbe22fd9 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -5152,5 +5152,44 @@ class Bar }", MainDescription($"void Program.Test()")); } + + [WorkItem(23883, "https://github.com/dotnet/roslyn/issues/23883")] + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task InMalformedEmbeddedStatement_01() + { + await TestAsync( +@" +class Program +{ + void method1() + { + if (method2()) + .Any(b => b.Content$$Type, out var chars) + { + } + } +} +"); + } + + [WorkItem(23883, "https://github.com/dotnet/roslyn/issues/23883")] + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task InMalformedEmbeddedStatement_02() + { + await TestAsync( +@" +class Program +{ + void method1() + { + if (method2()) + .Any(b => b$$.ContentType, out var chars) + { + } + } +} +", + MainDescription("(parameter) ? b")); + } } } -- GitLab