提交 c1308662 编写于 作者: A AlekseyTs

SemanticModel bug fixes: #948019 and #960755. (changeset 1276813)

上级 e4f5d13a
...@@ -278,7 +278,7 @@ internal BoundStatement BindPossibleEmbeddedStatement(StatementSyntax node, Diag ...@@ -278,7 +278,7 @@ internal BoundStatement BindPossibleEmbeddedStatement(StatementSyntax node, Diag
if (!locals.IsDefaultOrEmpty) if (!locals.IsDefaultOrEmpty)
{ {
result = new BoundBlock(node, locals, ImmutableArray.Create(result)) { WasCompilerGenerated = true }; result = new BoundBlock(node, locals, ImmutableArray.Create(result)) { WasCompilerGenerated = true };
} }
return result; return result;
} }
...@@ -2707,37 +2707,7 @@ internal virtual BoundForStatement BindForParts(DiagnosticBag diagnostics, Binde ...@@ -2707,37 +2707,7 @@ internal virtual BoundForStatement BindForParts(DiagnosticBag diagnostics, Binde
return this.Next.BindForParts(diagnostics, originalBinder); return this.Next.BindForParts(diagnostics, originalBinder);
} }
// TODO: Move this method into ForLoopBinder. Keep it here fo now for better diff. internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyntax nodeOpt, LocalDeclarationKind localDeclarationKind, DiagnosticBag diagnostics, out ImmutableArray<BoundLocalDeclaration> declarations)
internal BoundForStatement BindForParts(ForStatementSyntax node, Binder originalBinder, DiagnosticBag diagnostics)
{
BoundStatement initializer;
if (node.Declaration != null)
{
Debug.Assert(node.Initializers.Count == 0);
ImmutableArray<BoundLocalDeclaration> unused;
initializer = this.Next.BindForOrUsingOrFixedDeclarations(node.Declaration, LocalDeclarationKind.For, diagnostics, out unused);
}
else
{
initializer = this.Next.BindStatementExpressionList(node.Initializers, diagnostics);
}
var condition = (node.Condition != null) ? BindBooleanExpression(node.Condition, diagnostics) : null;
var increment = BindStatementExpressionList(node.Incrementors, diagnostics);
var body = originalBinder.BindPossibleEmbeddedStatement(node.Statement, diagnostics);
return new BoundForStatement(node,
ImmutableArray<LocalSymbol>.Empty,
initializer,
this.Locals,
condition,
increment,
body,
this.BreakLabel,
this.ContinueLabel);
}
protected BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyntax nodeOpt, LocalDeclarationKind localDeclarationKind, DiagnosticBag diagnostics, out ImmutableArray<BoundLocalDeclaration> declarations)
{ {
if (nodeOpt == null) if (nodeOpt == null)
{ {
...@@ -2782,7 +2752,7 @@ protected BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSy ...@@ -2782,7 +2752,7 @@ protected BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSy
new BoundMultipleLocalDeclarations(nodeOpt, declarations); new BoundMultipleLocalDeclarations(nodeOpt, declarations);
} }
private BoundStatement BindStatementExpressionList(SeparatedSyntaxList<ExpressionSyntax> statements, DiagnosticBag diagnostics) internal BoundStatement BindStatementExpressionList(SeparatedSyntaxList<ExpressionSyntax> statements, DiagnosticBag diagnostics)
{ {
int count = statements.Count; int count = statements.Count;
if (count == 0) if (count == 0)
......
...@@ -62,6 +62,36 @@ internal override BoundForStatement BindForParts(DiagnosticBag diagnostics, Bind ...@@ -62,6 +62,36 @@ internal override BoundForStatement BindForParts(DiagnosticBag diagnostics, Bind
return result; return result;
} }
private BoundForStatement BindForParts(ForStatementSyntax node, Binder originalBinder, DiagnosticBag diagnostics)
{
BoundStatement initializer;
if (node.Declaration != null)
{
Debug.Assert(node.Initializers.Count == 0);
ImmutableArray<BoundLocalDeclaration> unused;
initializer = this.Next.BindForOrUsingOrFixedDeclarations(node.Declaration, LocalDeclarationKind.For, diagnostics, out unused);
}
else
{
initializer = this.Next.BindStatementExpressionList(node.Initializers, diagnostics);
}
var condition = (node.Condition != null) ? BindBooleanExpression(node.Condition, diagnostics) : null;
var increment = BindStatementExpressionList(node.Incrementors, diagnostics);
var body = originalBinder.BindPossibleEmbeddedStatement(node.Statement, diagnostics);
return new BoundForStatement(node,
ImmutableArray<LocalSymbol>.Empty,
initializer,
this.Locals,
condition,
increment,
body,
this.BreakLabel,
this.ContinueLabel);
}
} }
internal sealed class ForLoopInitializationBinder : LocalScopeBinder internal sealed class ForLoopInitializationBinder : LocalScopeBinder
......
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.18449 // Runtime Version:4.0.30319.34014
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
...@@ -6856,7 +6856,7 @@ internal class CSharpResources { ...@@ -6856,7 +6856,7 @@ internal class CSharpResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to &apos;{0}&apos;: a parameter of a primary constructor cannot have the same name as containing type. /// Looks up a localized string similar to &apos;{0}&apos;: a parameter of a primary constructor cannot have the same name as containing type..
/// </summary> /// </summary>
internal static string ERR_PrimaryCtorParameterSameNameAsContainingType { internal static string ERR_PrimaryCtorParameterSameNameAsContainingType {
get { get {
...@@ -6865,7 +6865,7 @@ internal class CSharpResources { ...@@ -6865,7 +6865,7 @@ internal class CSharpResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to &apos;{0}&apos;: a parameter of a primary constructor cannot have the same name as a type&apos;s type parameter &apos;{1}&apos;. /// Looks up a localized string similar to &apos;{0}&apos;: a parameter of a primary constructor cannot have the same name as a type&apos;s type parameter &apos;{1}&apos;..
/// </summary> /// </summary>
internal static string ERR_PrimaryCtorParameterSameNameAsTypeParam { internal static string ERR_PrimaryCtorParameterSameNameAsTypeParam {
get { get {
......
...@@ -3787,10 +3787,10 @@ ...@@ -3787,10 +3787,10 @@
<value>Since this type has a primary constructor, all instance constructor declarations must specify a constructor initializer of the form this([argument-list]).</value> <value>Since this type has a primary constructor, all instance constructor declarations must specify a constructor initializer of the form this([argument-list]).</value>
</data> </data>
<data name="ERR_PrimaryCtorParameterSameNameAsTypeParam" xml:space="preserve"> <data name="ERR_PrimaryCtorParameterSameNameAsTypeParam" xml:space="preserve">
<value>'{0}': a parameter of a primary constructor cannot have the same name as a type's type parameter '{1}'</value> <value>'{0}': a parameter of a primary constructor cannot have the same name as a type's type parameter '{1}'.</value>
</data> </data>
<data name="ERR_PrimaryCtorParameterSameNameAsContainingType" xml:space="preserve"> <data name="ERR_PrimaryCtorParameterSameNameAsContainingType" xml:space="preserve">
<value>'{0}': a parameter of a primary constructor cannot have the same name as containing type</value> <value>'{0}': a parameter of a primary constructor cannot have the same name as containing type.</value>
</data> </data>
<data name="ERR_DuplicatePrimaryCtorBody" xml:space="preserve"> <data name="ERR_DuplicatePrimaryCtorBody" xml:space="preserve">
<value>Primary constructor already has a body.</value> <value>Primary constructor already has a body.</value>
......
...@@ -1723,24 +1723,7 @@ private bool IsInTypeofExpression(int position) ...@@ -1723,24 +1723,7 @@ private bool IsInTypeofExpression(int position)
ImmutableArray<Symbol> unusedHighestMemberGroup; ImmutableArray<Symbol> unusedHighestMemberGroup;
ImmutableArray<Symbol> highestSymbols = GetSemanticSymbols(highestBoundExpr, boundNodeForSyntacticParent, binderOpt, options, out highestIsDynamic, out highestResultKind, out unusedHighestMemberGroup); ImmutableArray<Symbol> highestSymbols = GetSemanticSymbols(highestBoundExpr, boundNodeForSyntacticParent, binderOpt, options, out highestIsDynamic, out highestResultKind, out unusedHighestMemberGroup);
// For an expression of the form (x.M is T) where x.M is a method group, we return an if ((symbols.Length != 1 || resultKind == LookupResultKind.OverloadResolutionFailure) && highestSymbols.Length > 0)
// arbitrary representative of the method group.
if (boundNodeForSyntacticParent != null && boundNodeForSyntacticParent.Kind == BoundKind.IsOperator && boundExpr.Kind == BoundKind.MethodGroup)
{
// Just take the first one that happens to be in our list. This code once tried to sort based
// on the LexicalOrderSymbolComparer, but that assumes that the symbols are in source, which is
// not always the case.
if (symbols.Length >= 1)
{
symbols = ImmutableArray.Create<Symbol>(symbols.First());
resultKind = LookupResultKind.Viable;
}
}
// Generally, we want to use the symbols from the LOWEST node. However, if the
// lowest node doesn't have symbols (or had an overload resolution failure), and
// the highest does, use those instead. Also, if the highest node has a WORSE
// resultKind, use that.
else if ((symbols.Length != 1 || resultKind == LookupResultKind.OverloadResolutionFailure) && highestSymbols.Length > 0)
{ {
symbols = highestSymbols; symbols = highestSymbols;
resultKind = highestResultKind; resultKind = highestResultKind;
...@@ -3731,6 +3714,11 @@ private static ImmutableArray<MethodSymbol> FilterOverriddenOrHiddenMethods(Immu ...@@ -3731,6 +3714,11 @@ private static ImmutableArray<MethodSymbol> FilterOverriddenOrHiddenMethods(Immu
default: default:
symbols = methodGroup; symbols = methodGroup;
if (symbols.Length > 0)
{
resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
}
break; break;
} }
} }
...@@ -3742,6 +3730,10 @@ private static ImmutableArray<MethodSymbol> FilterOverriddenOrHiddenMethods(Immu ...@@ -3742,6 +3730,10 @@ private static ImmutableArray<MethodSymbol> FilterOverriddenOrHiddenMethods(Immu
// one candidate, then we should probably succeed. // one candidate, then we should probably succeed.
symbols = methodGroup; symbols = methodGroup;
if (symbols.Length > 0)
{
resultKind = resultKind.WorseResultKind(LookupResultKind.OverloadResolutionFailure);
}
} }
if (!symbols.Any()) if (!symbols.Any())
......
...@@ -919,7 +919,7 @@ private MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node) ...@@ -919,7 +919,7 @@ private MemberSemanticModel GetOrAddModel(CSharpSyntaxNode node)
return this.memberModels.GetOrAdd(node, createMemberModelFunction); return this.memberModels.GetOrAdd(node, createMemberModelFunction);
} }
// Create a the member model for the given declaration syntax. In certain very malformed // Create a member model for the given declaration syntax. In certain very malformed
// syntax trees, there may not be a symbol that can have a member model associated with it // syntax trees, there may not be a symbol that can have a member model associated with it
// (although we try to minimize such cases). In such cases, null is returned. // (although we try to minimize such cases). In such cases, null is returned.
private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node) private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
......
...@@ -1460,7 +1460,7 @@ public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression ...@@ -1460,7 +1460,7 @@ public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression
return null; return null;
} }
protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpression node) protected override void VisitLvalueDeclarationExpression(BoundDeclarationExpression node)
{ {
LocalSymbol localSymbol = node.LocalSymbol; LocalSymbol localSymbol = node.LocalSymbol;
int slot = MakeSlot(localSymbol); // not initially assigned int slot = MakeSlot(localSymbol); // not initially assigned
...@@ -1474,7 +1474,7 @@ protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpres ...@@ -1474,7 +1474,7 @@ protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpres
if (node.InitializerOpt != null) if (node.InitializerOpt != null)
{ {
base.VisitLvaluetDeclarationExpression(node); base.VisitLvalueDeclarationExpression(node);
Assign(node, node.InitializerOpt); Assign(node, node.InitializerOpt);
} }
} }
......
...@@ -490,7 +490,7 @@ protected void VisitLvalue(BoundExpression node) ...@@ -490,7 +490,7 @@ protected void VisitLvalue(BoundExpression node)
break; break;
case BoundKind.DeclarationExpression: case BoundKind.DeclarationExpression:
VisitLvaluetDeclarationExpression((BoundDeclarationExpression)node); VisitLvalueDeclarationExpression((BoundDeclarationExpression)node);
break; break;
case BoundKind.FieldAccess: case BoundKind.FieldAccess:
...@@ -975,7 +975,7 @@ private void VisitDeclarationExpressionInitializer(BoundDeclarationExpression no ...@@ -975,7 +975,7 @@ private void VisitDeclarationExpressionInitializer(BoundDeclarationExpression no
} }
} }
protected virtual void VisitLvaluetDeclarationExpression(BoundDeclarationExpression node) protected virtual void VisitLvalueDeclarationExpression(BoundDeclarationExpression node)
{ {
VisitDeclarationExpressionInitializer(node); VisitDeclarationExpressionInitializer(node);
} }
......
...@@ -72,14 +72,14 @@ public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression ...@@ -72,14 +72,14 @@ public override BoundNode VisitDeclarationExpression(BoundDeclarationExpression
return base.VisitDeclarationExpression(node); return base.VisitDeclarationExpression(node);
} }
protected override void VisitLvaluetDeclarationExpression(BoundDeclarationExpression node) protected override void VisitLvalueDeclarationExpression(BoundDeclarationExpression node)
{ {
if (IsInside) if (IsInside)
{ {
variablesDeclared.Add(node.LocalSymbol); variablesDeclared.Add(node.LocalSymbol);
} }
base.VisitLvaluetDeclarationExpression(node); base.VisitLvalueDeclarationExpression(node);
} }
public override BoundNode VisitLambda(BoundLambda node) public override BoundNode VisitLambda(BoundLambda node)
......
...@@ -636,10 +636,11 @@ void M() ...@@ -636,10 +636,11 @@ void M()
Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, parentExpr.Kind); Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, parentExpr.Kind);
var parentInfo = model.GetSymbolInfo(parentExpr); var parentInfo = model.GetSymbolInfo(parentExpr);
Assert.NotNull(parentInfo); Assert.NotNull(parentInfo);
Assert.NotNull(parentInfo.Symbol); // the lexically first matching method Assert.Null(parentInfo.Symbol); // the lexically first matching method
Assert.Equal("void Color.M()", parentInfo.Symbol.ToTestDisplayString()); Assert.Equal(2, parentInfo.CandidateSymbols.Length);
Assert.Equal(CandidateReason.None, parentInfo.CandidateReason); Assert.Equal("void Color.M()", parentInfo.CandidateSymbols[0].ToTestDisplayString());
Assert.Equal(0, parentInfo.CandidateSymbols.Length); Assert.Equal("void Color.M(System.Int32 x)", parentInfo.CandidateSymbols[1].ToTestDisplayString());
Assert.Equal(CandidateReason.OverloadResolutionFailure, parentInfo.CandidateReason);
} }
[Fact] [Fact]
......
...@@ -1005,5 +1005,94 @@ protected void TryGetDocumentId(CancellationToken token) ...@@ -1005,5 +1005,94 @@ protected void TryGetDocumentId(CancellationToken token)
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "integrationService").WithArguments("TestDataPointBase.integrationService", "null").WithLocation(6, 54) Diagnostic(ErrorCode.WRN_UnassignedInternalField, "integrationService").WithArguments("TestDataPointBase.integrationService", "null").WithLocation(6, 54)
); );
} }
[Fact, WorkItem(960755, "DevDiv")]
public void Bug960755_01()
{
var source = @"
using System.Collections.Generic;
class C
{
static void M(IList<C> c)
{
var tmp = new C();
tmp.M((a, b) => c.Add);
}
}
";
var tree = SyntaxFactory.ParseSyntaxTree(source);
var comp = CreateCompilationWithMscorlib(tree);
var model = comp.GetSemanticModel(tree);
var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single().Body;
var symbolInfo = model.GetSymbolInfo(expr);
Assert.Null(symbolInfo.Symbol);
Assert.Equal("void System.Collections.Generic.ICollection<C>.Add(C item)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
}
[Fact, WorkItem(960755, "DevDiv")]
public void Bug960755_02()
{
var source = @"
using System.Collections.Generic;
class C
{
static void M(IList<C> c)
{
int tmp = c.Add;
}
}
";
var tree = SyntaxFactory.ParseSyntaxTree(source);
var comp = CreateCompilationWithMscorlib(tree);
var model = comp.GetSemanticModel(tree);
var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().Single().Initializer.Value;
var symbolInfo = model.GetSymbolInfo(expr);
Assert.Null(symbolInfo.Symbol);
Assert.Equal("void System.Collections.Generic.ICollection<C>.Add(C item)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
}
[Fact, WorkItem(960755, "DevDiv")]
public void Bug960755_03()
{
var source = @"
using System.Collections.Generic;
class C
{
static void M(IList<C> c)
{
var tmp = new C();
tmp.M((a, b) => c.Add);
}
static void M(System.Func<int, int, System.Action<C>> x)
{}
}
";
var tree = SyntaxFactory.ParseSyntaxTree(source);
var comp = CreateCompilationWithMscorlib(tree);
var model = comp.GetSemanticModel(tree);
var expr = (ExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single().Body;
var symbolInfo = model.GetSymbolInfo(expr);
Assert.Equal("void System.Collections.Generic.ICollection<C>.Add(C item)", symbolInfo.Symbol.ToTestDisplayString());
Assert.Equal(0, symbolInfo.CandidateSymbols.Length);
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
}
} }
} }
...@@ -1447,14 +1447,12 @@ static int Main(string[] args) ...@@ -1447,14 +1447,12 @@ static int Main(string[] args)
var model = compilation.GetSemanticModel(tree); var model = compilation.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<ExpressionSyntax>().Where(n => n.ToString() == "m.M").Single(); var node = tree.GetRoot().DescendantNodes().OfType<ExpressionSyntax>().Where(n => n.ToString() == "m.M").Single();
var symbolInfo = model.GetSymbolInfo(node); var symbolInfo = model.GetSymbolInfo(node);
Assert.Equal("M", symbolInfo.Symbol.Name); Assert.Equal("void I1.M()", symbolInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(SymbolKind.Method, symbolInfo.Symbol.Kind); Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
var node2 = (ExpressionSyntax)SyntaxFactory.SyntaxTree(node).GetRoot(); var node2 = (ExpressionSyntax)SyntaxFactory.SyntaxTree(node).GetRoot();
symbolInfo = model.GetSpeculativeSymbolInfo(node.Position, node2, SpeculativeBindingOption.BindAsExpression); symbolInfo = model.GetSpeculativeSymbolInfo(node.Position, node2, SpeculativeBindingOption.BindAsExpression);
Assert.Equal("M", symbolInfo.Symbol.Name); Assert.Equal("void I1.M()", symbolInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(SymbolKind.Method, symbolInfo.Symbol.Kind); Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
} }
private void TestLookupSymbolsNestedNamespaces(List<ISymbol> actual_lookupSymbols) private void TestLookupSymbolsNestedNamespaces(List<ISymbol> actual_lookupSymbols)
......
...@@ -3681,7 +3681,8 @@ static void M() ...@@ -3681,7 +3681,8 @@ static void M()
Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind); Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind);
var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression);
Assert.Equal(compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M"), info.Symbol); Assert.Equal(compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M"), info.CandidateSymbols.Single());
Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason);
} }
[WorkItem(544651, "DevDiv")] [WorkItem(544651, "DevDiv")]
...@@ -3740,7 +3741,8 @@ static void M() ...@@ -3740,7 +3741,8 @@ static void M()
Assert.Equal(SyntaxKind.IdentifierName, syntax.Kind); Assert.Equal(SyntaxKind.IdentifierName, syntax.Kind);
var info = model.GetSymbolInfo(syntax); var info = model.GetSymbolInfo(syntax);
Assert.Equal(compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M"), info.Symbol); Assert.Equal(compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M"), info.CandidateSymbols.Single());
Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason);
} }
[WorkItem(546046, "DevDiv")] [WorkItem(546046, "DevDiv")]
...@@ -4488,10 +4490,10 @@ int M(S s) ...@@ -4488,10 +4490,10 @@ int M(S s)
var structInfo = model.GetSymbolInfo(structMemberAccess); var structInfo = model.GetSymbolInfo(structMemberAccess);
// Only one candidate. // Only one candidate.
Assert.Equal(CandidateReason.None, classInfo.CandidateReason); Assert.Equal(CandidateReason.OverloadResolutionFailure, classInfo.CandidateReason);
Assert.Equal(classType, classInfo.Symbol.ContainingType); Assert.Equal("System.Int32 C.GetHashCode()", classInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(CandidateReason.None, structInfo.CandidateReason); Assert.Equal(CandidateReason.OverloadResolutionFailure, structInfo.CandidateReason);
Assert.Equal(structType, structInfo.Symbol.ContainingType); Assert.Equal("System.Int32 S.GetHashCode()", structInfo.CandidateSymbols.Single().ToTestDisplayString());
} }
[WorkItem(530252, "DevDiv")] [WorkItem(530252, "DevDiv")]
...@@ -4535,8 +4537,8 @@ static void Main(string[] args) ...@@ -4535,8 +4537,8 @@ static void Main(string[] args)
var info = model.GetSymbolInfo(memberAccess); var info = model.GetSymbolInfo(memberAccess);
// Only one candidate. // Only one candidate.
Assert.Equal(CandidateReason.None, info.CandidateReason); Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason);
Assert.Equal(classC, info.Symbol.ContainingType); Assert.Equal("void C.M()", info.CandidateSymbols.Single().ToTestDisplayString());
} }
[Fact] [Fact]
...@@ -4804,7 +4806,9 @@ void M() ...@@ -4804,7 +4806,9 @@ void M()
var equalsNode = equalsToken.Parent; var equalsNode = equalsToken.Parent;
var symbolInfo = model.GetSymbolInfo(equalsNode); var symbolInfo = model.GetSymbolInfo(equalsNode);
//note that we don't guarantee what symbol will come back on a method group in an is expression. //note that we don't guarantee what symbol will come back on a method group in an is expression.
Assert.NotNull(symbolInfo.Symbol); Assert.Null(symbolInfo.Symbol);
Assert.True(symbolInfo.CandidateSymbols.Length > 0);
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
} }
[Fact, WorkItem(531304, "DevDiv")] [Fact, WorkItem(531304, "DevDiv")]
......
...@@ -8557,11 +8557,9 @@ public static int Main(string[] args) ...@@ -8557,11 +8557,9 @@ public static int Main(string[] args)
Assert.Equal(TypeKind.Error, semanticInfo.ConvertedType.TypeKind); Assert.Equal(TypeKind.Error, semanticInfo.ConvertedType.TypeKind);
Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind); Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind);
Assert.NotNull(semanticInfo.Symbol); Assert.Null(semanticInfo.Symbol);
Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); Assert.Equal(CandidateReason.OverloadResolutionFailure, semanticInfo.CandidateReason);
Assert.Equal(0, semanticInfo.CandidateSymbols.Length); Assert.Equal("System.Int32 Test.M()", semanticInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal("System.Int32 Test.M()", semanticInfo.Symbol.ToTestDisplayString());
Assert.Equal(SymbolKind.Method, semanticInfo.Symbol.Kind);
Assert.Equal(1, semanticInfo.MethodGroup.Length); Assert.Equal(1, semanticInfo.MethodGroup.Length);
var sortedMethodGroup = semanticInfo.MethodGroup.OrderBy(s => s.ToTestDisplayString()).ToArray(); var sortedMethodGroup = semanticInfo.MethodGroup.OrderBy(s => s.ToTestDisplayString()).ToArray();
...@@ -8932,12 +8930,9 @@ public static int Main(string[] args) ...@@ -8932,12 +8930,9 @@ public static int Main(string[] args)
Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind); Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind);
Assert.Equal(ConversionKind.NoConversion, semanticInfo.ImplicitConversion.Kind); Assert.Equal(ConversionKind.NoConversion, semanticInfo.ImplicitConversion.Kind);
Assert.NotNull(semanticInfo.Symbol); Assert.Null(semanticInfo.Symbol);
Assert.Equal(CandidateReason.None, semanticInfo.CandidateReason); Assert.Equal(CandidateReason.OverloadResolutionFailure, semanticInfo.CandidateReason);
Assert.Equal(0, semanticInfo.CandidateSymbols.Length); Assert.Equal("System.Int32 Test.M()", semanticInfo.CandidateSymbols.Single().ToTestDisplayString());
var sortedCandidates = semanticInfo.CandidateSymbols.OrderBy(s => s.ToTestDisplayString()).ToArray();
Assert.Equal("System.Int32 Test.M()", semanticInfo.Symbol.ToTestDisplayString());
Assert.Equal(SymbolKind.Method, semanticInfo.Symbol.Kind);
Assert.Equal(1, semanticInfo.MethodGroup.Length); Assert.Equal(1, semanticInfo.MethodGroup.Length);
var sortedMethodGroup = semanticInfo.MethodGroup.OrderBy(s => s.ToTestDisplayString()).ToArray(); var sortedMethodGroup = semanticInfo.MethodGroup.OrderBy(s => s.ToTestDisplayString()).ToArray();
...@@ -14395,7 +14390,8 @@ class C { ...@@ -14395,7 +14390,8 @@ class C {
} }
"; ";
var semanticInfo = GetSemanticInfoForTest<IdentifierNameSyntax>(sourceCode); var semanticInfo = GetSemanticInfoForTest<IdentifierNameSyntax>(sourceCode);
Utils.CheckSymbol(semanticInfo.Symbol, "void C.M<T>(T t)"); Utils.CheckSymbol(semanticInfo.CandidateSymbols.Single(), "void C.M<T>(T t)");
Assert.Equal(CandidateReason.OverloadResolutionFailure, semanticInfo.CandidateReason);
Assert.Null(semanticInfo.Type); Assert.Null(semanticInfo.Type);
Utils.CheckSymbol(semanticInfo.ConvertedType, "D"); Utils.CheckSymbol(semanticInfo.ConvertedType, "D");
} }
......
using System.Collections.Generic; // Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Emit;
......
...@@ -330,11 +330,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -330,11 +330,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return New BoundConversion(node, Return New BoundConversion(node,
argument, argument,
ConversionKind:=Nothing, conversionKind:=Nothing,
checked:=CheckOverflow, checked:=CheckOverflow,
explicitCastInCode:=isExplicit, explicitCastInCode:=isExplicit,
Type:=targetType, type:=targetType,
HasErrors:=True) hasErrors:=True)
End If End If
If argument.HasErrors Then If argument.HasErrors Then
......
...@@ -2037,11 +2037,33 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2037,11 +2037,33 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' allow. ''' allow.
''' </summary> ''' </summary>
Public Function RecordNode(node As BoundNode, Optional allowCompilerGenerated As Boolean = False) As Boolean Public Function RecordNode(node As BoundNode, Optional allowCompilerGenerated As Boolean = False) As Boolean
If (Not allowCompilerGenerated AndAlso node.WasCompilerGenerated) OrElse node.Kind = BoundKind.UnboundLambda Then
' Don't cache compiler generated nodes or unbound lambdas (unbound lambda are converted into bound lambdas in VisitUnboundLambda.) If Not allowCompilerGenerated AndAlso node.WasCompilerGenerated Then
' Don't cache compiler generated nodes
Return False Return False
End If End If
Select Case node.Kind
Case BoundKind.UnboundLambda
' Don't cache unbound lambdas (unbound lambda are converted into bound lambdas in VisitUnboundLambda.)
Return False
Case BoundKind.Conversion
If Not allowCompilerGenerated Then
Dim conversion = DirectCast(node, BoundConversion)
If Not conversion.ExplicitCastInCode AndAlso conversion.Operand.WasCompilerGenerated Then
Select Case conversion.Operand.Kind
Case BoundKind.RValuePlaceholder,
BoundKind.LValuePlaceholder,
BoundKind.WithLValueExpressionPlaceholder,
BoundKind.WithRValueExpressionPlaceholder
' Don't cache compiler generated nodes
Return False
End Select
End If
End If
End Select
If _thisSyntaxNodeOnly IsNot Nothing AndAlso node.Syntax IsNot _thisSyntaxNodeOnly Then If _thisSyntaxNodeOnly IsNot Nothing AndAlso node.Syntax IsNot _thisSyntaxNodeOnly Then
' Didn't match the syntax node we're trying to handle ' Didn't match the syntax node we're trying to handle
Return False Return False
......
...@@ -738,6 +738,89 @@ BC30203: Identifier expected. ...@@ -738,6 +738,89 @@ BC30203: Identifier expected.
Assert.False(semanticInfo.ConstantValue.HasValue) Assert.False(semanticInfo.ConstantValue.HasValue)
End Sub End Sub
<Fact, WorkItem(960755, "DevDiv")>
Public Sub Bug960755_01()
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(
<compilation name="InstantiatingNamespace">
<file name="a.vb">
Imports System.Collections.Generic
Class C
Sub M(c As IList(Of C))
Dim tmp = New C()
tmp.M(Function(a, b) AddressOf c.Add) 'BIND:"c.Add"
End Sub
End Class
</file>
</compilation>)
Dim node = CompilationUtils.FindBindingText(Of ExpressionSyntax)(compilation, "a.vb")
Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree)
Dim symbolInfo = semanticModel.GetSymbolInfo(node)
Assert.Null(symbolInfo.Symbol)
Assert.Equal("Sub System.Collections.Generic.ICollection(Of C).Add(item As C)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString())
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason)
End Sub
<Fact, WorkItem(960755, "DevDiv")>
Public Sub Bug960755_02()
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(
<compilation name="InstantiatingNamespace">
<file name="a.vb">
Imports System.Collections.Generic
Class C
Sub M(c As IList(Of C))
Dim tmp As Integer = AddressOf c.Add 'BIND:"c.Add"
End Sub
End Class
</file>
</compilation>)
Dim node = CompilationUtils.FindBindingText(Of ExpressionSyntax)(compilation, "a.vb")
Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree)
Dim symbolInfo = semanticModel.GetSymbolInfo(node)
Assert.Null(symbolInfo.Symbol)
Assert.Equal("Sub System.Collections.Generic.ICollection(Of C).Add(item As C)", symbolInfo.CandidateSymbols.Single().ToTestDisplayString())
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason)
End Sub
<Fact, WorkItem(960755, "DevDiv")>
Public Sub Bug960755_03()
Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(
<compilation name="InstantiatingNamespace">
<file name="a.vb">
Imports System.Collections.Generic
Class C
Sub M(c As IList(Of C))
Dim tmp = New C()
tmp.M(Function(a, b) AddressOf c.Add) 'BIND:"c.Add"
End Sub
Sub M(x as System.Func(Of Integer, Integer, System.Action(Of C)))
End Sub
End Class
</file>
</compilation>)
Dim node = CompilationUtils.FindBindingText(Of ExpressionSyntax)(compilation, "a.vb")
Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree)
Dim symbolInfo = semanticModel.GetSymbolInfo(node)
Assert.Equal("Sub System.Collections.Generic.ICollection(Of C).Add(item As C)", symbolInfo.Symbol.ToTestDisplayString())
Assert.Equal(0, symbolInfo.CandidateSymbols.Length)
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason)
End Sub
End Class End Class
End Namespace End Namespace
...@@ -567,5 +567,79 @@ BC42016: Implicit conversion from 'Object' to 'Boolean'. ...@@ -567,5 +567,79 @@ BC42016: Implicit conversion from 'Object' to 'Boolean'.
</expected>) </expected>)
End Sub End Sub
<WorkItem(948019, "DevDiv")>
<Fact()>
Public Sub Bug948019_01()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Public Sub M(day As DayOfWeek)
Dim day2 = day
Select Case day 'BIND:"day"
Case DayOfWeek.A
Case
End Select
End Sub
Enum DayOfWeek
A
B
End Enum
End Class
]]></file>
</compilation>)
Dim node = CompilationUtils.FindBindingText(Of IdentifierNameSyntax)(compilation, "a.vb")
Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree)
Dim typeInfo = semanticModel.GetTypeInfo(node)
Assert.Equal("C.DayOfWeek", typeInfo.Type.ToTestDisplayString())
Assert.Equal("C.DayOfWeek", typeInfo.ConvertedType.ToTestDisplayString())
Assert.Equal(ConversionKind.Identity, semanticModel.GetConversion(node).Kind)
Dim symbolInfo = semanticModel.GetSymbolInfo(node)
Assert.Equal("day As C.DayOfWeek", symbolInfo.Symbol.ToTestDisplayString())
Assert.Equal(SymbolKind.Parameter, symbolInfo.Symbol.Kind)
End Sub
<WorkItem(948019, "DevDiv")>
<Fact()>
Public Sub Bug948019_02()
Dim compilation = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Class C
Public Sub M(day As DayOfWeek)
Dim day2 = day
Select Case day 'BIND:"day"
Case DayOfWeek.A
Case 2
End Select
End Sub
Enum DayOfWeek
A
B
End Enum
End Class
]]></file>
</compilation>)
Dim node = CompilationUtils.FindBindingText(Of IdentifierNameSyntax)(compilation, "a.vb")
Dim semanticModel = compilation.GetSemanticModel(node.SyntaxTree)
Dim typeInfo = semanticModel.GetTypeInfo(node)
Assert.Equal("C.DayOfWeek", typeInfo.Type.ToTestDisplayString())
Assert.Equal("C.DayOfWeek", typeInfo.ConvertedType.ToTestDisplayString())
Assert.Equal(ConversionKind.Identity, semanticModel.GetConversion(node).Kind)
Dim symbolInfo = semanticModel.GetSymbolInfo(node)
Assert.Equal("day As C.DayOfWeek", symbolInfo.Symbol.ToTestDisplayString())
Assert.Equal(SymbolKind.Parameter, symbolInfo.Symbol.Kind)
End Sub
End Class End Class
End Namespace End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册