提交 75c66bc9 编写于 作者: A AlekseyTs 提交者: GitHub

Merge pull request #17061 from AlekseyTs/Issue16919_post-dev15

Improve error recovery around lambdas in MemberSemnticModel.GetEnclosingBinderInternal
......@@ -23,9 +23,7 @@ internal sealed class TypeofBinder : Binder
internal TypeofBinder(ExpressionSyntax typeExpression, Binder next)
// Unsafe types are not unsafe in typeof, so it is effectively an unsafe region.
// Since we only depend on existence of nameable members and nameof(x) produces a constant
// string expression usable in an early attribute, we use early attribute binding.
: base(next, next.Flags | BinderFlags.UnsafeRegion | BinderFlags.EarlyAttributeBinding)
: base(next, next.Flags | BinderFlags.UnsafeRegion)
{
OpenTypeVisitor.Visit(typeExpression, out _allowedMap, out _isTypeExpressionOpen);
}
......
......@@ -903,17 +903,7 @@ private CSharpSyntaxNode Body
{
get
{
var syntax = UnboundLambda.Syntax;
switch (syntax.Kind())
{
default:
case SyntaxKind.SimpleLambdaExpression:
return ((SimpleLambdaExpressionSyntax)syntax).Body;
case SyntaxKind.ParenthesizedLambdaExpression:
return ((ParenthesizedLambdaExpressionSyntax)syntax).Body;
case SyntaxKind.AnonymousMethodExpression:
return ((AnonymousMethodExpressionSyntax)syntax).Block;
}
return UnboundLambda.Syntax.AnonymousFunctionBody();
}
}
......
......@@ -423,20 +423,20 @@ internal static bool IsInAnonymousFunctionOrQuery(int position, SyntaxNode lambd
{
case SyntaxKind.SimpleLambdaExpression:
SimpleLambdaExpressionSyntax simple = (SimpleLambdaExpressionSyntax)lambdaExpressionOrQueryNode;
firstIncluded = simple.Parameter.Identifier;
firstIncluded = simple.ArrowToken;
body = simple.Body;
break;
case SyntaxKind.ParenthesizedLambdaExpression:
ParenthesizedLambdaExpressionSyntax parenthesized = (ParenthesizedLambdaExpressionSyntax)lambdaExpressionOrQueryNode;
firstIncluded = parenthesized.ParameterList.OpenParenToken;
firstIncluded = parenthesized.ArrowToken;
body = parenthesized.Body;
break;
case SyntaxKind.AnonymousMethodExpression:
AnonymousMethodExpressionSyntax anon = (AnonymousMethodExpressionSyntax)lambdaExpressionOrQueryNode;
firstIncluded = anon.DelegateKeyword;
body = anon.Block;
firstIncluded = body.GetFirstToken(includeZeroWidth:true);
break;
default:
......
......@@ -2,6 +2,7 @@
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -99,6 +100,22 @@ internal static bool IsValidScopeDesignator(this ExpressionSyntax expression)
}
}
internal static CSharpSyntaxNode AnonymousFunctionBody(this SyntaxNode lambda)
{
switch (lambda.Kind())
{
case SyntaxKind.SimpleLambdaExpression:
return ((SimpleLambdaExpressionSyntax)lambda).Body;
case SyntaxKind.ParenthesizedLambdaExpression:
return ((ParenthesizedLambdaExpressionSyntax)lambda).Body;
case SyntaxKind.AnonymousMethodExpression:
return ((AnonymousMethodExpressionSyntax)lambda).Block;
default:
throw ExceptionUtilities.UnexpectedValue(lambda.Kind());
}
}
/// <summary>
/// Given an initializer expression infer the name of anonymous property.
/// Returns default(SyntaxToken) if unsuccessful
......
......@@ -701,13 +701,13 @@ public void TestLambdas()
var text = @"
class C
`{
System.Func<int, int> f1 = `x => x`;
System.Func<int, int> f2 = `x => `{ int y; return x; `};
System.Func<int, int> f1 = x `=> x`;
System.Func<int, int> f2 = x `=> `{ int y; return x; `};
void M()
`{
System.Func<int, int> g1 = `x => x`;
System.Func<int, int> g2 = `x => `{ int y; return x; `};
System.Func<int, int> g1 = x `=> x`;
System.Func<int, int> g2 = x `=> `{ int y; return x; `};
`}
`}
";
......@@ -751,13 +751,13 @@ public void TestNestedLambdas()
var text = @"
class C
`{
System.Func<int, System.Func<int, int>> f1 = `x => `y => x + y`;
System.Func<int, System.Func<int, int>> f2 = `x => `{ int y; `{int z; return `a => x`; `} `};
System.Func<int, System.Func<int, int>> f1 = x `=> y `=> x + y`;
System.Func<int, System.Func<int, int>> f2 = x `=> `{ int y; `{int z; return a `=> x`; `} `};
void M()
`{
System.Func<int, System.Func<int, int>> g1 = `x => `y => x + y`;
System.Func<int, System.Func<int, int>> g2 = `x => `{ int y; `{int z; return `a => x`; `} `};
System.Func<int, System.Func<int, int>> g1 = x `=> y `=> x + y`;
System.Func<int, System.Func<int, int>> g2 = x `=> `{ int y; `{int z; return a `=> x`; `} `};
`}
`}
";
......@@ -866,9 +866,9 @@ public void TestLambdaInConstructorInitializer()
class C
`{
public C(System.Func<int, int> x) `{ `}
public C() : this(`a => a`)
public C() : this(a `=> a`)
{
M(`b => b`);
M(b `=> b`);
}
private void M(System.Func<int, int> f) `{ `}
......@@ -910,7 +910,7 @@ class C
private void M(System.Func<int, int> f) `{ `}
public C()
{
M(`b =>
M(b `=>
";
var expectedNames = MakeExpectedSymbols(
......@@ -945,7 +945,7 @@ class C
private void M(System.Func<int, int> f) `{ `}
public C()
{
M(`b => `);
M(b `=> `);
}
`}
";
......
......@@ -31456,6 +31456,368 @@ public static void Main(string[] args)
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("System.Int32", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_01()
{
string source = @"
class C
{
void M<T>()
{
void Local1 (Action<T> onNext = p =>
{
weakRef.TryGetTarget(out var x);
})
{
}
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType)); // crashes
var decl = GetOutVarDeclaration(tree, "x");
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_02()
{
string source = @"
class C
{
void M<T>()
{
void Local1 (Action<T> onNext = p1 =>
{
void Local1 (Action<T> onNext = p2 =>
{
weakRef.TryGetTarget(out var x);
})
{
}
})
{
}
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType)); // crashes
var decl = GetOutVarDeclaration(tree, "x");
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_03()
{
string source = @"
class C
{
void M<T>()
{
void Local1 (Action<T> onNext = p1 =>
{
void Local1 (Action<T> onNext = p2 =>
{
void Local1 (Action<T> onNext = p3 =>
{
weakRef.TryGetTarget(out var x);
})
{
}
})
{
}
})
{
}
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType)); // crashes
var decl = GetOutVarDeclaration(tree, "x");
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_04()
{
string source = @"
class C
{
void M<T>()
{
void Local1 (object onNext = from p in y select weakRef.TryGetTarget(out var x))
{
}
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType)); // crashes
var decl = GetOutVarDeclaration(tree, "x");
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_05()
{
string source = @"
class C
{
void M<T>()
{
void Local1 (object onNext = from p in y
select (Action<T>)( p =>
{
void Local2 (object onNext = from p in y select weakRef.TryGetTarget(out var x))
{
}
}
)
)
{
}
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType)); // crashes
var decl = GetOutVarDeclaration(tree, "x");
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_06()
{
string source = @"
class C
{
void M<T>()
{
System.Type t = typeof(int[p =>
{
weakRef.TryGetTarget(out var x);
}]);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType));
var decl = GetOutVarDeclaration(tree, "x");
Assert.Equal("var", model.GetTypeInfo(decl).Type.ToTestDisplayString()); // crashes
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_07()
{
string source = @"
class C
{
void M<T>()
{
System.Type t1 = typeof(int[p1 =>
{
System.Type t2 = typeof(int[p2 =>
{
weakRef.TryGetTarget(out var x);
}]);
}]);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType));
var decl = GetOutVarDeclaration(tree, "x");
Assert.Equal("var", model.GetTypeInfo(decl).Type.ToTestDisplayString()); // crashes
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_08()
{
string source = @"
class C
{
void M<T>()
{
System.Type t1 = typeof(int[p1 =>
{
System.Type t2 = typeof(int[p2 =>
{
System.Type t3 = typeof(int[p3 =>
{
weakRef.TryGetTarget(out var x);
}]);
}]);
}]);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType));
var decl = GetOutVarDeclaration(tree, "x");
Assert.Equal("var", model.GetTypeInfo(decl).Type.ToTestDisplayString()); // crashes
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_09()
{
string source = @"
class C
{
void M<T>()
{
System.Type t = typeof(int[from p in y select weakRef.TryGetTarget(out var x)]);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType));
var decl = GetOutVarDeclaration(tree, "x");
Assert.Equal("var", model.GetTypeInfo(decl).Type.ToTestDisplayString()); // crashes
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(16919, "https://github.com/dotnet/roslyn/issues/16919")]
[WorkItem(378641, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=378641")]
public void GetEnclosingBinderInternalRecovery_10()
{
string source = @"
class C
{
void M<T>()
{
System.Type t1 = typeof(int[from p in y
select (Action<T>)( p =>
{
System.Type t2 = typeof(int[from p in y select weakRef.TryGetTarget(out var x)]);
}
)
]
);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees.First();
var model = compilation.GetSemanticModel(tree);
var varType = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "var").Single();
Assert.Equal("var", varType.ToString());
Assert.Null(model.GetAliasInfo(varType));
var decl = GetOutVarDeclaration(tree, "x");
Assert.Equal("var", model.GetTypeInfo(decl).Type.ToTestDisplayString()); // crashes
VerifyModelForOutVarInNotExecutableCode(model, decl);
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("var", symbol.Type.ToTestDisplayString());
}
}
internal static class OutVarTestsExtensions
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
......@@ -47,6 +48,11 @@ void M()
Assert.Equal(expected, LambdaUtilities.IsLambdaBody(node, allowReducedLambdas: true));
Assert.Equal(isLambdaBody || isReducedLambdaBody, expected);
Assert.Equal(isLambdaBody, LambdaUtilities.IsLambdaBody(node));
var methodDef = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Where(d => d.Identifier.ValueText == "M").Single();
Assert.Equal("C", model.GetEnclosingSymbol(methodDef.SpanStart).ToTestDisplayString());
Assert.Equal("C", model.GetEnclosingSymbol(methodDef.ParameterList.CloseParenToken.SpanStart).ToTestDisplayString());
Assert.Equal("void C.M()", model.GetEnclosingSymbol(methodDef.Body.SpanStart).ToTestDisplayString());
}
[Fact]
......
......@@ -131,7 +131,7 @@ public UniqueSymbolOrArities(int arity, TSymbol uniqueSymbol)
public void AddSymbol(TSymbol symbol, int arity)
{
if (symbol == _uniqueSymbolOrArities)
if (symbol != null && symbol == _uniqueSymbolOrArities)
{
Debug.Assert(arity == _arityBitVectorOrUniqueArity);
return;
......
......@@ -959,7 +959,7 @@ internal override SyntaxNode GetLambda(SyntaxNode lambdaBody)
internal override IMethodSymbol GetLambdaExpressionSymbol(SemanticModel model, SyntaxNode lambdaExpression, CancellationToken cancellationToken)
{
return (IMethodSymbol)model.GetEnclosingSymbol(lambdaExpression.SpanStart, cancellationToken);
return (IMethodSymbol)model.GetEnclosingSymbol(((AnonymousFunctionExpressionSyntax)lambdaExpression).Body.SpanStart, cancellationToken);
}
internal override SyntaxNode GetContainingQueryExpression(SyntaxNode node)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册