/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Compilation/GetSemanticInfoTests.cs
6 157 строк
215 KB
AlekseyTs
Assert the shape of bound tree created for user defined conversions (#81896)
08 янв 2026, 00:55
Не верифицирован
08 янв 2026, 00:55
b5872bb
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public partial class GetSemanticInfoTests : SemanticModelTestBase { [WorkItem(544320, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544320")] [Fact] public void TestBug12592() { var text = @" class B { public B(int x = 42) {} } class D : B { public D(int y) : base(/*<bind>*/x/*</bind>*/: y) { } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.Equal(SymbolKind.Parameter, sym.Symbol.Kind); Assert.Equal("x", sym.Symbol.Name); } [WorkItem(541948, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541948")] [Fact] public void DelegateArgumentType() { var text = @"using System; delegate void MyEvent(); class Test { event MyEvent Clicked; void Handler() { } public void Run() { Test t = new Test(); t.Clicked += new MyEvent(/*<bind>*/Handler/*</bind>*/); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.Equal(SymbolKind.Method, sym.Symbol.Kind); var info = model.GetTypeInfo(expr); Assert.Null(info.Type); Assert.NotNull(info.ConvertedType); } [WorkItem(541949, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541949")] [Fact] public void LambdaWithParenthesis_BindOutsideOfParenthesis() { var text = @"using System; public class Test { delegate int D(); static void Main(int xx) { // int x = (xx); D d = /*<bind>*/( delegate() { return 0; } )/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.NotNull(sym.Symbol); Assert.Equal(SymbolKind.Method, sym.Symbol.Kind); var info = model.GetTypeInfo(expr); var conv = model.GetConversion(expr); Assert.Equal(ConversionKind.AnonymousFunction, conv.Kind); Assert.Null(info.Type); Assert.NotNull(info.ConvertedType); Assert.Equal("Test.D", info.ConvertedType.ToTestDisplayString()); } [WorkItem(529056, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529056")] [WorkItem(529056, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529056")] [Fact] public void LambdaWithParenthesis_BindInsideOfParenthesis() { var text = @"using System; public class Test { delegate int D(); static void Main(int xx) { // int x = (xx); D d = (/*<bind>*/ delegate() { return 0; }/*</bind>*/) ; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.NotNull(sym.Symbol); Assert.Equal(SymbolKind.Method, sym.Symbol.Kind); var info = model.GetTypeInfo(expr); var conv = model.GetConversion(expr); Assert.Equal(ConversionKind.AnonymousFunction, conv.Kind); Assert.Null(info.Type); Assert.NotNull(info.ConvertedType); Assert.Equal("Test.D", info.ConvertedType.ToTestDisplayString()); } [Fact, WorkItem(528656, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528656")] public void SemanticInfoForInvalidExpression() { var text = @" public class A { static void Main() { Console.WriteLine(/*<bind>*/ delegate * delegate /*</bind>*/); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.Null(sym.Symbol); } [WorkItem(541973, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541973")] [Fact] public void LambdaAsAttributeArgumentErr() { var text = @"using System; delegate void D(); class MyAttr: Attribute { public MyAttr(D d) { } } [MyAttr((D)/*<bind>*/delegate { }/*</bind>*/)] // CS0182 public class A { } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var info = model.GetTypeInfo(expr); Assert.Null(info.Type); Assert.NotNull(info.ConvertedType); } [Fact] public void ClassifyConversionImplicit() { var text = @"using System; enum E { One, Two, Three } public class Test { static byte[] ary; static int Main() { // Identity ary = new byte[3]; // ImplicitConstant ary[0] = 0x0F; // ImplicitNumeric ushort ret = ary[0]; // ImplicitReference Test obj = null; // Identity obj = new Test(); // ImplicitNumeric obj.M(ary[0]); // boxing object box = -1; // ImplicitEnumeration E e = 0; // Identity E e2 = E.Two; // bind 'Two' return (int)ret; } void M(ulong p) { } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var testClass = tree.GetCompilationUnitRoot().Members[1] as TypeDeclarationSyntax; Assert.Equal(3, testClass.Members.Count); var mainMethod = testClass.Members[1] as MethodDeclarationSyntax; var mainStats = mainMethod.Body.Statements; Assert.Equal(10, mainStats.Count); // ary = new byte[3]; var v1 = (mainStats[0] as ExpressionStatementSyntax).Expression; Assert.Equal(SyntaxKind.SimpleAssignmentExpression, v1.Kind()); ConversionTestHelper(model, (v1 as AssignmentExpressionSyntax).Right, ConversionKind.Identity, ConversionKind.Identity); // ary[0] = 0x0F; var v2 = (mainStats[1] as ExpressionStatementSyntax).Expression; ConversionTestHelper(model, (v2 as AssignmentExpressionSyntax).Right, ConversionKind.ImplicitConstant, ConversionKind.ExplicitNumeric); // ushort ret = ary[0]; var v3 = (mainStats[2] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v3[0].Initializer.Value, ConversionKind.ImplicitNumeric, ConversionKind.ImplicitNumeric); // object obj01 = null; var v4 = (mainStats[3] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v4[0].Initializer.Value, ConversionKind.ImplicitReference, ConversionKind.NoConversion); // obj.M(ary[0]); var v6 = (mainStats[5] as ExpressionStatementSyntax).Expression; Assert.Equal(SyntaxKind.InvocationExpression, v6.Kind()); var v61 = (v6 as InvocationExpressionSyntax).ArgumentList.Arguments; ConversionTestHelper(model, v61[0].Expression, ConversionKind.ImplicitNumeric, ConversionKind.ImplicitNumeric); // object box = -1; var v7 = (mainStats[6] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v7[0].Initializer.Value, ConversionKind.Boxing, ConversionKind.Boxing); // E e = 0; var v8 = (mainStats[7] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v8[0].Initializer.Value, ConversionKind.ImplicitEnumeration, ConversionKind.ExplicitEnumeration); // E e2 = E.Two; var v9 = (mainStats[8] as LocalDeclarationStatementSyntax).Declaration.Variables; var v9val = (MemberAccessExpressionSyntax)(v9[0].Initializer.Value); var v9right = v9val.Name; ConversionTestHelper(model, v9right, ConversionKind.Identity, ConversionKind.Identity); } private void TestClassifyConversionBuiltInNumeric(string from, string to, ConversionKind ck) { const string template = @" class C {{ static void Goo({1} v) {{ }} static void Main() {{ {0} v = default({0}); Goo({2}v); }} }} "; var isExplicitConversion = ck == ConversionKind.ExplicitNumeric; var source = string.Format(template, from, to, isExplicitConversion ? "(" + to + ")" : ""); var tree = Parse(source); var comp = CreateCompilation(tree); comp.VerifyDiagnostics(); var model = comp.GetSemanticModel(tree); var c = (TypeDeclarationSyntax)tree.GetCompilationUnitRoot().Members[0]; var main = (MethodDeclarationSyntax)c.Members[1]; var call = (InvocationExpressionSyntax)((ExpressionStatementSyntax)main.Body.Statements[1]).Expression; var arg = call.ArgumentList.Arguments[0].Expression; if (isExplicitConversion) { ConversionTestHelper(model, ((CastExpressionSyntax)arg).Expression, model.GetTypeInfo(arg).ConvertedType, ck); } else { ConversionTestHelper(model, arg, ck, ck); } } [Fact] public void ClassifyConversionBuiltInNumeric() { const ConversionKind ID = ConversionKind.Identity; const ConversionKind IN = ConversionKind.ImplicitNumeric; const ConversionKind XN = ConversionKind.ExplicitNumeric; var types = new[] { "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", "char", "float", "double", "decimal" }; var conversions = new ConversionKind[,] { // to sb b s us i ui l ul c f d m // from /* sb */ { ID, XN, IN, XN, IN, XN, IN, XN, XN, IN, IN, IN }, /* b */ { XN, ID, IN, IN, IN, IN, IN, IN, XN, IN, IN, IN }, /* s */ { XN, XN, ID, XN, IN, XN, IN, XN, XN, IN, IN, IN }, /* us */ { XN, XN, XN, ID, IN, IN, IN, IN, XN, IN, IN, IN }, /* i */ { XN, XN, XN, XN, ID, XN, IN, XN, XN, IN, IN, IN }, /* ui */ { XN, XN, XN, XN, XN, ID, IN, IN, XN, IN, IN, IN }, /* l */ { XN, XN, XN, XN, XN, XN, ID, XN, XN, IN, IN, IN }, /* ul */ { XN, XN, XN, XN, XN, XN, XN, ID, XN, IN, IN, IN }, /* c */ { XN, XN, XN, IN, IN, IN, IN, IN, ID, IN, IN, IN }, /* f */ { XN, XN, XN, XN, XN, XN, XN, XN, XN, ID, IN, XN }, /* d */ { XN, XN, XN, XN, XN, XN, XN, XN, XN, XN, ID, XN }, /* m */ { XN, XN, XN, XN, XN, XN, XN, XN, XN, XN, XN, ID } }; for (var from = 0; from < types.Length; from++) { for (var to = 0; to < types.Length; to++) { TestClassifyConversionBuiltInNumeric(types[from], types[to], conversions[from, to]); } } } [WorkItem(527486, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527486")] [Fact] public void ClassifyConversionExplicit() { var text = @"using System; public class Test { object obj01; public void Testing(int x, Test obj02) { uint y = 5678; // Cast y = (uint) x; // Boxing obj01 = x; // Cast x = (int)obj01; // NoConversion obj02 = (Test)obj01; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var testClass = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax; Assert.Equal(2, testClass.Members.Count); var mainMethod = testClass.Members[1] as MethodDeclarationSyntax; var mainStats = mainMethod.Body.Statements; Assert.Equal(5, mainStats.Count); // y = (uint) x; var v1 = ((mainStats[1] as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax).Right; ConversionTestHelper(model, (v1 as CastExpressionSyntax).Expression, comp.GetSpecialType(SpecialType.System_UInt32), ConversionKind.ExplicitNumeric); // obj01 = x; var v2 = (mainStats[2] as ExpressionStatementSyntax).Expression; ConversionTestHelper(model, (v2 as AssignmentExpressionSyntax).Right, comp.GetSpecialType(SpecialType.System_Object), ConversionKind.Boxing); // x = (int)obj01; var v3 = ((mainStats[3] as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax).Right; ConversionTestHelper(model, (v3 as CastExpressionSyntax).Expression, comp.GetSpecialType(SpecialType.System_Int32), ConversionKind.Unboxing); // obj02 = (Test)obj01; var tsym = comp.SourceModule.GlobalNamespace.GetTypeMembers("Test").FirstOrDefault(); var v4 = ((mainStats[4] as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax).Right; ConversionTestHelper(model, (v4 as CastExpressionSyntax).Expression, tsym, ConversionKind.ExplicitReference); } [Fact] public void DiagnosticsInStages() { var text = @" public class Test { object obj01; public void Testing(int x, Test obj02) { // ExplicitReference -> CS0266 obj02 = obj01; } binding error; parse err } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var errs = model.GetDiagnostics(); Assert.Equal(4, errs.Count()); errs = model.GetSyntaxDiagnostics(); Assert.Equal(1, errs.Count()); errs = model.GetDeclarationDiagnostics(); Assert.Equal(2, errs.Count()); errs = model.GetMethodBodyDiagnostics(); Assert.Equal(1, errs.Count()); } [Fact] public void DiagnosticsFilteredWithPragmas() { var text = @" public class Test { #pragma warning disable 1633 #pragma xyzzy whatever #pragma warning restore 1633 } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var errs = model.GetDiagnostics(); Assert.Equal(0, errs.Count()); errs = model.GetSyntaxDiagnostics(); Assert.Equal(0, errs.Count()); } [Fact] public void ClassifyConversionExplicitNeg() { var text = @" public class Test { object obj01; public void Testing(int x, Test obj02) { uint y = 5678; // ExplicitNumeric - CS0266 y = x; // Boxing obj01 = x; // unboxing - CS0266 x = obj01; // ExplicitReference -> CS0266 obj02 = obj01; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var testClass = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax; Assert.Equal(2, testClass.Members.Count); var mainMethod = testClass.Members[1] as MethodDeclarationSyntax; var mainStats = mainMethod.Body.Statements; Assert.Equal(5, mainStats.Count); // y = x; var v1 = ((mainStats[1] as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax).Right; ConversionTestHelper(model, v1, ConversionKind.ExplicitNumeric, ConversionKind.ExplicitNumeric); // x = obj01; var v2 = ((mainStats[3] as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax).Right; ConversionTestHelper(model, v2, ConversionKind.Unboxing, ConversionKind.Unboxing); // obj02 = obj01; var v3 = ((mainStats[4] as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax).Right; ConversionTestHelper(model, v3, ConversionKind.ExplicitReference, ConversionKind.ExplicitReference); // CC var errs = model.GetDiagnostics(); Assert.Equal(3, errs.Count()); errs = model.GetDeclarationDiagnostics(); Assert.Equal(0, errs.Count()); } [WorkItem(527767, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527767")] [Fact] public void ClassifyConversionNullable() { var text = @"using System; public class Test { static void Main() { // NullLiteral sbyte? nullable = null; // ImplicitNullable uint? nullable01 = 100; ushort localVal = 123; // ImplicitNullable nullable01 = localVal; E e = 0; E? en = 0; // Oddly enough, C# classifies this as an implicit enumeration conversion. } } enum E { zero, one } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var testClass = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax; Assert.Equal(1, testClass.Members.Count); var mainMethod = testClass.Members[0] as MethodDeclarationSyntax; var mainStats = mainMethod.Body.Statements; Assert.Equal(6, mainStats.Count); // sbyte? nullable = null; var v1 = (mainStats[0] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v1[0].Initializer.Value, ConversionKind.NullLiteral, ConversionKind.NoConversion); // uint? nullable01 = 100; var v2 = (mainStats[1] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v2[0].Initializer.Value, ConversionKind.ImplicitNullable, ConversionKind.ExplicitNullable); // nullable01 = localVal; var v3 = (mainStats[3] as ExpressionStatementSyntax).Expression; Assert.Equal(SyntaxKind.SimpleAssignmentExpression, v3.Kind()); ConversionTestHelper(model, (v3 as AssignmentExpressionSyntax).Right, ConversionKind.ImplicitNullable, ConversionKind.ImplicitNullable); // E e = 0; var v4 = (mainStats[4] as LocalDeclarationStatementSyntax).Declaration.Variables; ConversionTestHelper(model, v4[0].Initializer.Value, ConversionKind.ImplicitEnumeration, ConversionKind.ExplicitEnumeration); // E? en = 0; var v5 = (mainStats[5] as LocalDeclarationStatementSyntax).Declaration.Variables; // Bug#5035 (ByDesign): Conversion from literal 0 to nullable enum is Implicit Enumeration (not ImplicitNullable). Conversion from int to nullable enum is Explicit Nullable. ConversionTestHelper(model, v5[0].Initializer.Value, ConversionKind.ImplicitEnumeration, ConversionKind.ExplicitNullable); } [Fact, WorkItem(543994, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543994")] public void ClassifyConversionImplicitUserDef() { var text = @"using System; class MyClass { public static bool operator true(MyClass p) { return true; } public static bool operator false(MyClass p) { return false; } public static MyClass operator &(MyClass mc1, MyClass mc2) { return new MyClass(); } public static int Main() { var cls1 = new MyClass(); var cls2 = new MyClass(); if (/*<bind0>*/cls1/*</bind0>*/) return 0; if (/*<bind1>*/cls1 && cls2/*</bind1>*/) return 1; return 2; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprs = GetBindingNodes<ExpressionSyntax>(comp); var expr1 = exprs.First(); var expr2 = exprs.Last(); var info = model.GetTypeInfo(expr1); Assert.NotEqual(default, info); Assert.NotNull(info.ConvertedType); // It was ImplicitUserDef -> Design Meeting resolution: not expose op_True|False as conversion through API var impconv = model.GetConversion(expr1); Assert.Equal(Conversion.Identity, impconv); Conversion conv = model.ClassifyConversion(expr1, info.ConvertedType); CheckIsAssignableTo(model, expr1); Assert.Equal(impconv, conv); Assert.Equal("Identity", conv.ToString()); conv = model.ClassifyConversion(expr2, info.ConvertedType); CheckIsAssignableTo(model, expr2); Assert.Equal(impconv, conv); } [Fact, WorkItem(1019372, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1019372")] public void ClassifyConversionImplicitUserDef02() { var text = @" class C { public static implicit operator int(C c) { return 0; } public C() { int? i = /*<bind0>*/this/*</bind0>*/; } }"; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprs = GetBindingNodes<ExpressionSyntax>(comp); var expr1 = exprs.First(); var info = model.GetTypeInfo(expr1); Assert.NotEqual(default, info); Assert.NotNull(info.ConvertedType); var impconv = model.GetConversion(expr1); Assert.True(impconv.IsImplicit); Assert.True(impconv.IsUserDefined); Conversion conv = model.ClassifyConversion(expr1, info.ConvertedType); CheckIsAssignableTo(model, expr1); Assert.Equal(impconv.Kind, conv.Kind); Assert.Equal(impconv.Method, conv.Method); Assert.True(conv.IsImplicit); Assert.True(conv.IsUserDefined); } private void CheckIsAssignableTo(SemanticModel model, ExpressionSyntax syntax) { var info = model.GetTypeInfo(syntax); var conversion = info.Type != null && info.ConvertedType != null ? model.Compilation.ClassifyConversion(info.Type, info.ConvertedType) : Conversion.NoConversion; Assert.Equal(conversion.IsImplicit, model.Compilation.HasImplicitConversion(info.Type, info.ConvertedType)); } [Fact, WorkItem(544151, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544151")] public void PublicViewOfPointerConversions() { ValidateConversion(Conversion.PointerToVoid, ConversionKind.ImplicitPointerToVoid); ValidateConversion(Conversion.NullToPointer, ConversionKind.ImplicitNullToPointer); ValidateConversion(Conversion.PointerToPointer, ConversionKind.ExplicitPointerToPointer); ValidateConversion(Conversion.IntegerToPointer, ConversionKind.ExplicitIntegerToPointer); ValidateConversion(Conversion.PointerToInteger, ConversionKind.ExplicitPointerToInteger); ValidateConversion(Conversion.IntPtr, ConversionKind.IntPtr); } #region "Conversion helper" private void ValidateConversion(Conversion conv, ConversionKind kind) { Assert.Equal(conv.Kind, kind); switch (kind) { case ConversionKind.NoConversion: Assert.False(conv.Exists); Assert.False(conv.IsImplicit); Assert.False(conv.IsExplicit); break; case ConversionKind.Identity: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsIdentity); break; case ConversionKind.ImplicitNumeric: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsNumeric); break; case ConversionKind.ImplicitEnumeration: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsEnumeration); break; case ConversionKind.ImplicitNullable: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsNullable); break; case ConversionKind.NullLiteral: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsNullLiteral); break; case ConversionKind.ImplicitReference: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsReference); break; case ConversionKind.Boxing: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsBoxing); break; case ConversionKind.ImplicitDynamic: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsDynamic); break; case ConversionKind.ExplicitDynamic: Assert.True(conv.Exists); Assert.True(conv.IsExplicit); Assert.False(conv.IsImplicit); Assert.True(conv.IsDynamic); break; case ConversionKind.ImplicitConstant: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsConstantExpression); break; case ConversionKind.ImplicitUserDefined: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsUserDefined); break; case ConversionKind.AnonymousFunction: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsAnonymousFunction); break; case ConversionKind.MethodGroup: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.True(conv.IsMethodGroup); break; case ConversionKind.ExplicitNumeric: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.True(conv.IsNumeric); break; case ConversionKind.ExplicitEnumeration: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.True(conv.IsEnumeration); break; case ConversionKind.ExplicitNullable: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.True(conv.IsNullable); break; case ConversionKind.ExplicitReference: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.True(conv.IsReference); break; case ConversionKind.Unboxing: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.True(conv.IsUnboxing); break; case ConversionKind.ExplicitUserDefined: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.True(conv.IsUserDefined); break; case ConversionKind.ImplicitNullToPointer: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.False(conv.IsUserDefined); Assert.True(conv.IsPointer); break; case ConversionKind.ImplicitPointerToVoid: Assert.True(conv.Exists); Assert.True(conv.IsImplicit); Assert.False(conv.IsExplicit); Assert.False(conv.IsUserDefined); Assert.True(conv.IsPointer); break; case ConversionKind.ExplicitPointerToPointer: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.False(conv.IsUserDefined); Assert.True(conv.IsPointer); break; case ConversionKind.ExplicitIntegerToPointer: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.False(conv.IsUserDefined); Assert.True(conv.IsPointer); break; case ConversionKind.ExplicitPointerToInteger: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.False(conv.IsUserDefined); Assert.True(conv.IsPointer); break; case ConversionKind.IntPtr: Assert.True(conv.Exists); Assert.False(conv.IsImplicit); Assert.True(conv.IsExplicit); Assert.False(conv.IsUserDefined); Assert.False(conv.IsPointer); Assert.True(conv.IsIntPtr); break; } } /// <summary> /// /// </summary> /// <param name="semanticModel"></param> /// <param name="expr"></param> /// <param name="ept1">expr -> TypeInParent</param> /// <param name="ept2">Type(expr) -> TypeInParent</param> private void ConversionTestHelper(SemanticModel semanticModel, ExpressionSyntax expr, ConversionKind ept1, ConversionKind ept2) { var info = semanticModel.GetTypeInfo(expr); Assert.NotEqual(default, info); Assert.NotNull(info.ConvertedType); var conv = semanticModel.GetConversion(expr); // NOT expect NoConversion Conversion act1 = semanticModel.ClassifyConversion(expr, info.ConvertedType); CheckIsAssignableTo(semanticModel, expr); Assert.Equal(ept1, act1.Kind); ValidateConversion(act1, ept1); ValidateConversion(act1, conv.Kind); if (ept2 == ConversionKind.NoConversion) { Assert.Null(info.Type); } else { Assert.NotNull(info.Type); var act2 = semanticModel.Compilation.ClassifyConversion(info.Type, info.ConvertedType); Assert.Equal(ept2, act2.Kind); ValidateConversion(act2, ept2); } } private void ConversionTestHelper(SemanticModel semanticModel, ExpressionSyntax expr, ITypeSymbol expsym, ConversionKind expkind) { var info = semanticModel.GetTypeInfo(expr); Assert.NotEqual(default, info); Assert.NotNull(info.ConvertedType); // NOT expect NoConversion Conversion act1 = semanticModel.ClassifyConversion(expr, expsym); CheckIsAssignableTo(semanticModel, expr); Assert.Equal(expkind, act1.Kind); ValidateConversion(act1, expkind); } #endregion [Fact] public void EnumOffsets() { // sbyte EnumOffset(ConstantValue.Create((sbyte)sbyte.MinValue), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((sbyte)(sbyte.MinValue + 1))); EnumOffset(ConstantValue.Create((sbyte)sbyte.MinValue), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((sbyte)(sbyte.MinValue + 2))); EnumOffset(ConstantValue.Create((sbyte)-2), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((sbyte)(-1))); EnumOffset(ConstantValue.Create((sbyte)-2), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((sbyte)(1))); EnumOffset(ConstantValue.Create((sbyte)(sbyte.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((sbyte)sbyte.MaxValue)); EnumOffset(ConstantValue.Create((sbyte)(sbyte.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((sbyte)(sbyte.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // byte EnumOffset(ConstantValue.Create((byte)0), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((byte)1)); EnumOffset(ConstantValue.Create((byte)0), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((byte)2)); EnumOffset(ConstantValue.Create((byte)(byte.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((byte)byte.MaxValue)); EnumOffset(ConstantValue.Create((byte)(byte.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((byte)(byte.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // short EnumOffset(ConstantValue.Create((short)short.MinValue), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((short)(short.MinValue + 1))); EnumOffset(ConstantValue.Create((short)short.MinValue), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((short)(short.MinValue + 2))); EnumOffset(ConstantValue.Create((short)-2), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((short)(-1))); EnumOffset(ConstantValue.Create((short)-2), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((short)(1))); EnumOffset(ConstantValue.Create((short)(short.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((short)short.MaxValue)); EnumOffset(ConstantValue.Create((short)(short.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((short)(short.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // ushort EnumOffset(ConstantValue.Create((ushort)0), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((ushort)1)); EnumOffset(ConstantValue.Create((ushort)0), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((ushort)2)); EnumOffset(ConstantValue.Create((ushort)(ushort.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((ushort)ushort.MaxValue)); EnumOffset(ConstantValue.Create((ushort)(ushort.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((ushort)(ushort.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // int EnumOffset(ConstantValue.Create((int)int.MinValue), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((int)(int.MinValue + 1))); EnumOffset(ConstantValue.Create((int)int.MinValue), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((int)(int.MinValue + 2))); EnumOffset(ConstantValue.Create((int)-2), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((int)(-1))); EnumOffset(ConstantValue.Create((int)-2), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((int)(1))); EnumOffset(ConstantValue.Create((int)(int.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((int)int.MaxValue)); EnumOffset(ConstantValue.Create((int)(int.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((int)(int.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // uint EnumOffset(ConstantValue.Create((uint)0), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((uint)1)); EnumOffset(ConstantValue.Create((uint)0), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((uint)2)); EnumOffset(ConstantValue.Create((uint)(uint.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((uint)uint.MaxValue)); EnumOffset(ConstantValue.Create((uint)(uint.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((uint)(uint.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // long EnumOffset(ConstantValue.Create((long)long.MinValue), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((long)(long.MinValue + 1))); EnumOffset(ConstantValue.Create((long)long.MinValue), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((long)(long.MinValue + 2))); EnumOffset(ConstantValue.Create((long)-2), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((long)(-1))); EnumOffset(ConstantValue.Create((long)-2), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((long)(1))); EnumOffset(ConstantValue.Create((long)(long.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((long)long.MaxValue)); EnumOffset(ConstantValue.Create((long)(long.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((long)(long.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); // ulong EnumOffset(ConstantValue.Create((ulong)0), 1, EnumOverflowKind.NoOverflow, ConstantValue.Create((ulong)1)); EnumOffset(ConstantValue.Create((ulong)0), 2, EnumOverflowKind.NoOverflow, ConstantValue.Create((ulong)2)); EnumOffset(ConstantValue.Create((ulong)(ulong.MaxValue - 3)), 3, EnumOverflowKind.NoOverflow, ConstantValue.Create((ulong)ulong.MaxValue)); EnumOffset(ConstantValue.Create((ulong)(ulong.MaxValue - 3)), 4, EnumOverflowKind.OverflowReport, ConstantValue.Bad); EnumOffset(ConstantValue.Create((ulong)(ulong.MaxValue - 3)), 5, EnumOverflowKind.OverflowIgnore, ConstantValue.Bad); } private void EnumOffset(ConstantValue constantValue, uint offset, EnumOverflowKind expectedOverflowKind, ConstantValue expectedValue) { ConstantValue actualValue; var actualOverflowKind = EnumConstantHelper.OffsetValue(constantValue, offset, out actualValue); Assert.Equal(expectedOverflowKind, actualOverflowKind); Assert.Equal(expectedValue, actualValue); } [Fact] public void TestGetSemanticInfoInParentInIf() { var compilation = CreateCompilation(@" class C { void M(int x) { if (x == 10) {} } } "); var tree = compilation.SyntaxTrees[0]; var methodDecl = (MethodDeclarationSyntax)((TypeDeclarationSyntax)tree.GetCompilationUnitRoot().Members[0]).Members[0]; var ifStatement = (IfStatementSyntax)methodDecl.Body.Statements[0]; var condition = ifStatement.Condition; var model = compilation.GetSemanticModel(tree); var info = model.GetSemanticInfoSummary(condition); Assert.NotNull(info.ConvertedType); Assert.Equal("Boolean", info.Type.Name); Assert.Equal("System.Boolean System.Int32.op_Equality(System.Int32 left, System.Int32 right)", info.Symbol.ToTestDisplayString()); Assert.Equal(0, info.CandidateSymbols.Length); } [Fact] public void TestGetSemanticInfoInParentInFor() { var compilation = CreateCompilation(@" class C { void M(int x) { for (int i = 0; i < 10; i = i + 1) { } } } "); var tree = compilation.SyntaxTrees[0]; var methodDecl = (MethodDeclarationSyntax)((TypeDeclarationSyntax)tree.GetCompilationUnitRoot().Members[0]).Members[0]; var forStatement = (ForStatementSyntax)methodDecl.Body.Statements[0]; var condition = forStatement.Condition; var model = compilation.GetSemanticModel(tree); var info = model.GetSemanticInfoSummary(condition); Assert.NotNull(info.ConvertedType); Assert.Equal("Boolean", info.ConvertedType.Name); Assert.Equal("System.Boolean System.Int32.op_LessThan(System.Int32 left, System.Int32 right)", info.Symbol.ToTestDisplayString()); Assert.Equal(0, info.CandidateSymbols.Length); } [WorkItem(540279, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540279")] [Fact] public void NoMembersForVoidReturnType() { var text = @" class C { void M() { /*<bind>*/System.Console.WriteLine()/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); IMethodSymbol methodSymbol = (IMethodSymbol)bindInfo.Symbol; ITypeSymbol returnType = methodSymbol.ReturnType; var symbols = model.LookupSymbols(0, returnType); Assert.Equal(0, symbols.Length); } [WorkItem(540767, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540767")] [Fact] public void BindIncompleteVarDeclWithDoKeyword() { var code = @" class Test { static int Main(string[] args) { do"; var compilation = CreateCompilation(code); var tree = compilation.SyntaxTrees[0]; var model = compilation.GetSemanticModel(tree); var exprSyntaxList = GetExprSyntaxList(tree); Assert.Equal(6, exprSyntaxList.Count); // Note the omitted array size expression in "string[]" Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxList[4].Kind()); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxList[5].Kind()); Assert.Equal("", exprSyntaxList[4].ToFullString()); Assert.Equal("", exprSyntaxList[5].ToFullString()); var exprSyntaxToBind = exprSyntaxList[exprSyntaxList.Count - 2]; model.GetSemanticInfoSummary(exprSyntaxToBind); } [Fact] public void TestBindBaseConstructorInitializer() { var text = @" class C { C() : base() { } } "; var bindInfo = BindFirstConstructorInitializer(text); Assert.NotEqual(default, bindInfo); var baseConstructor = bindInfo.Symbol; Assert.Equal(SymbolKind.Method, baseConstructor.Kind); Assert.Equal(MethodKind.Constructor, ((IMethodSymbol)baseConstructor).MethodKind); Assert.Equal("System.Object..ctor()", baseConstructor.ToTestDisplayString()); } [Fact] public void TestBindThisConstructorInitializer() { var text = @" class C { C() : this(1) { } C(int x) { } } "; var bindInfo = BindFirstConstructorInitializer(text); Assert.NotEqual(default, bindInfo); var baseConstructor = bindInfo.Symbol; Assert.Equal(SymbolKind.Method, baseConstructor.Kind); Assert.Equal(MethodKind.Constructor, ((IMethodSymbol)baseConstructor).MethodKind); Assert.Equal("C..ctor(System.Int32 x)", baseConstructor.ToTestDisplayString()); } [WorkItem(540862, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540862")] [Fact] public void BindThisStaticConstructorInitializer() { var text = @" class MyClass { static MyClass() : this() { intI = 2; } public MyClass() { } static int intI = 1; } "; var bindInfo = BindFirstConstructorInitializer(text); Assert.NotEqual(default, bindInfo); var invokedConstructor = (IMethodSymbol)bindInfo.Symbol; Assert.Equal(MethodKind.Constructor, invokedConstructor.MethodKind); Assert.Equal("MyClass..ctor()", invokedConstructor.ToTestDisplayString()); } [WorkItem(541053, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541053")] [Fact] public void CheckAndAdjustPositionOutOfRange() { var text = @" using System; > 1 "; var tree = Parse(text, options: TestOptions.Script); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var root = tree.GetCompilationUnitRoot(); Assert.NotEqual(0, root.SpanStart); var stmt = (GlobalStatementSyntax)root.Members.Single(); var expr = ((ExpressionStatementSyntax)stmt.Statement).Expression; Assert.Equal(SyntaxKind.GreaterThanExpression, expr.Kind()); var info = model.GetSemanticInfoSummary(expr); Assert.Equal(SpecialType.System_Boolean, info.Type.SpecialType); } [Fact] public void AddAccessorValueParameter() { var text = @" class C { private System.Action e; event System.Action E { add { e += /*<bind>*/value/*</bind>*/; } remove { e -= value; } } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var systemActionType = GetSystemActionType(comp); Assert.Equal(systemActionType, bindInfo.Type); var parameterSymbol = (IParameterSymbol)bindInfo.Symbol; Assert.Equal(systemActionType, parameterSymbol.Type); Assert.Equal("value", parameterSymbol.Name); Assert.Equal(MethodKind.EventAdd, ((IMethodSymbol)parameterSymbol.ContainingSymbol).MethodKind); } [Fact] public void RemoveAccessorValueParameter() { var text = @" class C { private System.Action e; event System.Action E { add { e += value; } remove { e -= /*<bind>*/value/*</bind>*/; } } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var systemActionType = GetSystemActionType(comp); Assert.Equal(systemActionType, bindInfo.Type); var parameterSymbol = (IParameterSymbol)bindInfo.Symbol; Assert.Equal(systemActionType, parameterSymbol.Type); Assert.Equal("value", parameterSymbol.Name); Assert.Equal(MethodKind.EventRemove, ((IMethodSymbol)parameterSymbol.ContainingSymbol).MethodKind); } [Fact] public void FieldLikeEventInitializer() { var text = @" class C { event System.Action E = /*<bind>*/new System.Action(() => { })/*</bind>*/; } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var systemActionType = GetSystemActionType(comp); Assert.Equal(systemActionType, bindInfo.Type); Assert.Null(bindInfo.Symbol); Assert.Equal(0, bindInfo.CandidateSymbols.Length); Assert.Equal(CandidateReason.None, bindInfo.CandidateReason); } [Fact] public void FieldLikeEventInitializer2() { var text = @" class C { event System.Action E = new /*<bind>*/System.Action/*</bind>*/(() => { }); } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var systemActionType = GetSystemActionType(comp); Assert.Equal("System.Action", bindInfo.Type.ToTestDisplayString()); Assert.Equal(systemActionType, bindInfo.Symbol); } [Fact] public void CustomEventAccess() { var text = @" class C { event System.Action E { add { } remove { } } void Method() { /*<bind>*/E/*</bind>*/ += null; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var systemActionType = GetSystemActionType(comp); Assert.Equal(systemActionType, bindInfo.Type); var eventSymbol = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IEventSymbol>("E"); Assert.Equal(eventSymbol, bindInfo.Symbol); } [Fact] public void FieldLikeEventAccess() { var text = @" class C { event System.Action E; void Method() { /*<bind>*/E/*</bind>*/ += null; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var systemActionType = GetSystemActionType(comp); Assert.Equal(systemActionType, bindInfo.Type); var eventSymbol = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IEventSymbol>("E"); Assert.Equal(eventSymbol, bindInfo.Symbol); } [Fact] public void CustomEventAssignmentOperator() { var text = @" class C { event System.Action E { add { } remove { } } void Method() { /*<bind>*/E += null/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); Assert.Equal(SpecialType.System_Void, bindInfo.Type.SpecialType); var eventSymbol = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IEventSymbol>("E"); Assert.Equal(eventSymbol.AddMethod, bindInfo.Symbol); } [Fact] public void FieldLikeEventAssignmentOperator() { var text = @" class C { event System.Action E; void Method() { /*<bind>*/E += null/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); Assert.Equal(SpecialType.System_Void, bindInfo.Type.SpecialType); var eventSymbol = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IEventSymbol>("E"); Assert.Equal(eventSymbol.AddMethod, bindInfo.Symbol); } [Fact] public void CustomEventMissingAssignmentOperator() { var text = @" class C { event System.Action E { /*add { }*/ remove { } } //missing add void Method() { /*<bind>*/E += null/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); Assert.Null(bindInfo.Symbol); Assert.Equal(0, bindInfo.CandidateSymbols.Length); Assert.Equal(SpecialType.System_Void, bindInfo.Type.SpecialType); } private static INamedTypeSymbol GetSystemActionType(CSharpCompilation comp) { return GetSystemActionType((Compilation)comp); } private static INamedTypeSymbol GetSystemActionType(Compilation comp) { return (INamedTypeSymbol)comp.GlobalNamespace.GetMember<INamespaceSymbol>("System").GetMembers("Action").Where(s => !((INamedTypeSymbol)s).IsGenericType).Single(); } [Fact] public void IndexerAccess() { var text = @" class C { int this[int x] { get { return x; } } int this[int x, int y] { get { return x + y; } } void Method() { int x = /*<bind>*/this[1]/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.ElementAccessExpression, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var indexerSymbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Where(i => i.ParameterCount == 1).Single().GetPublicSymbol(); Assert.Equal(indexerSymbol, bindInfo.Symbol); Assert.Equal(0, bindInfo.CandidateSymbols.Length); Assert.Equal(CandidateReason.None, bindInfo.CandidateReason); Assert.Equal(SpecialType.System_Int32, bindInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Int32, bindInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, bindInfo.ImplicitConversion.Kind); Assert.Equal(CandidateReason.None, bindInfo.CandidateReason); Assert.Equal(0, bindInfo.MethodGroup.Length); Assert.False(bindInfo.IsCompileTimeConstant); Assert.Null(bindInfo.ConstantValue.Value); } [Fact] public void IndexerAccessOverloadResolutionFailure() { var text = @" class C { int this[int x] { get { return x; } } int this[int x, int y] { get { return x + y; } } void Method() { int x = /*<bind>*/this[1, 2, 3]/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.ElementAccessExpression, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var indexerSymbol1 = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Where(i => i.ParameterCount == 1).Single().GetPublicSymbol(); var indexerSymbol2 = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").Indexers.Where(i => i.ParameterCount == 2).Single().GetPublicSymbol(); var candidateIndexers = ImmutableArray.Create<ISymbol>(indexerSymbol1, indexerSymbol2); Assert.Null(bindInfo.Symbol); Assert.True(bindInfo.CandidateSymbols.SetEquals(candidateIndexers, EqualityComparer<ISymbol>.Default)); Assert.Equal(CandidateReason.OverloadResolutionFailure, bindInfo.CandidateReason); Assert.Equal(SpecialType.System_Int32, bindInfo.Type.SpecialType); //still have the type since all candidates agree Assert.Equal(SpecialType.System_Int32, bindInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, bindInfo.ImplicitConversion.Kind); Assert.Equal(CandidateReason.OverloadResolutionFailure, bindInfo.CandidateReason); Assert.Equal(0, bindInfo.MethodGroup.Length); Assert.False(bindInfo.IsCompileTimeConstant); Assert.Null(bindInfo.ConstantValue.Value); } [Fact] public void IndexerAccessNoIndexers() { var text = @" class C { void Method() { int x = /*<bind>*/this[1, 2, 3]/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.ElementAccessExpression, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); Assert.Null(bindInfo.Symbol); Assert.Equal(0, bindInfo.CandidateSymbols.Length); Assert.Equal(CandidateReason.None, bindInfo.CandidateReason); Assert.Equal(TypeKind.Error, bindInfo.Type.TypeKind); Assert.Equal(TypeKind.Struct, bindInfo.ConvertedType.TypeKind); Assert.Equal(ConversionKind.NoConversion, bindInfo.ImplicitConversion.Kind); Assert.Equal(CandidateReason.None, bindInfo.CandidateReason); Assert.Equal(0, bindInfo.MethodGroup.Length); Assert.False(bindInfo.IsCompileTimeConstant); Assert.Null(bindInfo.ConstantValue.Value); } [WorkItem(542296, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542296")] [Fact] public void TypeArgumentsOnFieldAccess1() { var text = @" public class Test { public int Fld; public int Func() { return (int)(/*<bind>*/Fld<int>/*</bind>*/); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.GenericName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); Assert.Null(bindInfo.Symbol); Assert.Equal(CandidateReason.WrongArity, bindInfo.CandidateReason); Assert.Equal(1, bindInfo.CandidateSymbols.Length); var candidate = bindInfo.CandidateSymbols.Single(); Assert.Equal(SymbolKind.Field, candidate.Kind); Assert.Equal("Fld", candidate.Name); } [WorkItem(542296, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542296")] [Fact] public void TypeArgumentsOnFieldAccess2() { var text = @" public class Test { public int Fld; public int Func() { return (int)(Fld</*<bind>*/Test/*</bind>*/>); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.NotNull(symbol); Assert.Equal(SymbolKind.NamedType, symbol.Kind); Assert.Equal("Test", symbol.Name); } [WorkItem(528785, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528785")] [Fact] public void TopLevelIndexer() { var text = @" this[double E] { get { return /*<bind>*/E/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.Null(symbol); } [WorkItem(542360, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542360")] [Fact] public void TypeAndMethodHaveSameTypeParameterName() { var text = @" interface I<T> { void Goo<T>(); } class A<T> : I<T> { void I</*<bind>*/T/*</bind>*/>.Goo<T>() { } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.NotNull(symbol); Assert.Equal(SymbolKind.TypeParameter, symbol.Kind); Assert.Equal("T", symbol.Name); Assert.Equal(comp.GlobalNamespace.GetMember<INamedTypeSymbol>("A"), symbol.ContainingSymbol); //from the type, not the method } [WorkItem(542436, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542436")] [Fact] public void RecoveryFromBadNamespaceDeclaration() { var text = @"namespace alias:: using alias = /*<bind>*/N/*</bind>*/; namespace N { } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); } /// Test that binding a local declared with var binds the same way when localSymbol.Type is called before BindVariableDeclaration. /// Assert occurs if the two do not compute the same type. [Fact] [WorkItem(542634, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542634")] public void VarInitializedWithStaticType() { var text = @"using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; class Program { static string xunit = " + "@" + @"..\..\Closed\Tools\xUnit\xunit.console.x86.exe" + @"; static string test = " + @"Roslyn.VisualStudio.Services.UnitTests.dll" + @"; static string commandLine = test" + @" /html log.html" + @"; static void Main(string[] args) { var options = CreateOptions(); /*<bind>*/Parallel/*</bind>*/.For(0, 100, RunTest, options); } private static Parallel CreateOptions() { var result = new ParallelOptions(); } private static void RunTest(int i) { } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); // Bind Parallel from line Parallel.For(0, 100, RunTest, options); // This will implicitly bind "var" to determine type of options. // This calls LocalSymbol.GetType var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var varIdentifier = (IdentifierNameSyntax)tree.GetCompilationUnitRoot().DescendantNodes().First(n => n.ToString() == "var"); // var from line var options = CreateOptions; // Explicitly bind "var". // This path calls BindvariableDeclaration. bindInfo = model.GetSemanticInfoSummary(varIdentifier); } [WorkItem(542186, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542186")] [Fact] public void IndexerParameter() { var text = @" class C { int this[int x] { get { return /*<bind>*/x/*</bind>*/; } } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.NotNull(symbol); Assert.Equal(SymbolKind.Parameter, symbol.Kind); Assert.Equal("x", symbol.Name); Assert.Equal(SymbolKind.Method, symbol.ContainingSymbol.Kind); var lookupSymbols = model.LookupSymbols(exprSyntaxToBind.SpanStart, name: "x"); Assert.Equal(symbol, lookupSymbols.Single()); } [WorkItem(542186, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542186")] [Fact] public void IndexerValueParameter() { var text = @" class C { int this[int x] { set { x = /*<bind>*/value/*</bind>*/; } } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.NotNull(symbol); Assert.Equal(SymbolKind.Parameter, symbol.Kind); Assert.Equal("value", symbol.Name); Assert.Equal(SymbolKind.Method, symbol.ContainingSymbol.Kind); var lookupSymbols = model.LookupSymbols(exprSyntaxToBind.SpanStart, name: "value"); Assert.Equal(symbol, lookupSymbols.Single()); } [WorkItem(542777, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542777")] [Fact] public void IndexerThisParameter() { var text = @" class C { int this[int x] { set { System.Console.Write(/*<bind>*/this/*</bind>*/); } } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.ThisExpression, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.NotNull(symbol); Assert.Equal(SymbolKind.Parameter, symbol.Kind); Assert.Equal("this", symbol.Name); Assert.Equal(SymbolKind.Method, symbol.ContainingSymbol.Kind); } [WorkItem(542592, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542592")] [Fact] public void TypeParameterParamsParameter() { var text = @" class Test<T> { public void Method(params T arr) { } } class Program { static void Main(string[] args) { new Test<int[]>()./*<bind>*/Method/*</bind>*/(new int[][] { }); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSemanticInfoSummary(exprSyntaxToBind); var symbol = bindInfo.Symbol; Assert.Null(symbol); Assert.Equal(CandidateReason.OverloadResolutionFailure, bindInfo.CandidateReason); var candidate = (IMethodSymbol)bindInfo.CandidateSymbols.Single(); Assert.Equal("void Test<System.Int32[]>.Method(params System.Int32[] arr)", candidate.ToTestDisplayString()); Assert.Equal(TypeKind.Array, candidate.Parameters.Last().Type.TypeKind); Assert.Equal(TypeKind.TypeParameter, ((IMethodSymbol)candidate.OriginalDefinition).Parameters.Last().Type.TypeKind); } [WorkItem(542458, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542458")] [Fact] public void ParameterDefaultValues() { var text = @" struct S { void M( int i = 1, string str = ""hello"", object o = null, S s = default(S)) { /*<bind>*/M/*</bind>*/(); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSymbolInfo(exprSyntaxToBind); var method = (IMethodSymbol)bindInfo.Symbol; Assert.NotNull(method); var parameters = method.Parameters; Assert.Equal(4, parameters.Length); Assert.True(parameters[0].HasExplicitDefaultValue); Assert.Equal(1, parameters[0].ExplicitDefaultValue); Assert.True(parameters[1].HasExplicitDefaultValue); Assert.Equal("hello", parameters[1].ExplicitDefaultValue); Assert.True(parameters[2].HasExplicitDefaultValue); Assert.Null(parameters[2].ExplicitDefaultValue); Assert.True(parameters[3].HasExplicitDefaultValue); Assert.Null(parameters[3].ExplicitDefaultValue); } [WorkItem(542764, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542764")] [Fact] public void UnboundGenericTypeArity() { var text = @" class C<T, U, V> { void M() { System.Console.Write(typeof(/*<bind>*/C<,,>/*</bind>*/)); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var nameSyntaxToBind = (SimpleNameSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.GenericName, nameSyntaxToBind.Kind()); Assert.Equal(3, nameSyntaxToBind.Arity); var bindInfo = model.GetSymbolInfo(nameSyntaxToBind); var type = (INamedTypeSymbol)bindInfo.Symbol; Assert.NotNull(type); Assert.True(type.IsUnboundGenericType); Assert.Equal(3, type.Arity); Assert.Equal("C<,,>", type.ToTestDisplayString()); } [Fact] public void GetType_VoidArray() { var text = @" class C { void M() { var x = typeof(/*<bind>*/System.Void[]/*</bind>*/); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.ArrayType, exprSyntaxToBind.Kind()); var bindInfo = model.GetSymbolInfo(exprSyntaxToBind); var arrayType = (IArrayTypeSymbol)bindInfo.Symbol; Assert.NotNull(arrayType); Assert.Equal("System.Void[]", arrayType.ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterDiamondInheritance1() { var text = @" using System.Linq; public interface IA { object P { get; } } public interface IB : IA { } public class C<T> where T : IA, IB // can find IA.P in two different ways { void M() { new T[1]./*<bind>*/Select/*</bind>*/(i => i.P); } } "; var tree = Parse(text); var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree }); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSymbolInfo(exprSyntaxToBind); Assert.Equal("System.Collections.Generic.IEnumerable<System.Object> System.Collections.Generic.IEnumerable<T>.Select<T, System.Object>(System.Func<T, System.Object> selector)", bindInfo.Symbol.ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterDiamondInheritance2() //add hiding member in derived interface { var text = @" using System.Linq; public interface IA { object P { get; } } public interface IB : IA { new int P { get; } } public class C<T> where T : IA, IB { void M() { new T[1]./*<bind>*/Select/*</bind>*/(i => i.P); } } "; var tree = Parse(text); var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree }); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSymbolInfo(exprSyntaxToBind); Assert.Equal("System.Collections.Generic.IEnumerable<System.Int32> System.Collections.Generic.IEnumerable<T>.Select<T, System.Int32>(System.Func<T, System.Int32> selector)", bindInfo.Symbol.ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterDiamondInheritance3() //reverse order of interface list (shouldn't matter) { var text = @" using System.Linq; public interface IA { object P { get; } } public interface IB : IA { new int P { get; } } public class C<T> where T : IB, IA { void M() { new T[1]./*<bind>*/Select/*</bind>*/(i => i.P); } } "; var tree = Parse(text); var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree }); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSymbolInfo(exprSyntaxToBind); Assert.Equal("System.Collections.Generic.IEnumerable<System.Int32> System.Collections.Generic.IEnumerable<T>.Select<T, System.Int32>(System.Func<T, System.Int32> selector)", bindInfo.Symbol.ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterDiamondInheritance4() //Two interfaces with a common base { var text = @" using System.Linq; public interface IA { object P { get; } } public interface IB : IA { } public interface IC : IA { } public class C<T> where T : IB, IC { void M() { new T[1]./*<bind>*/Select/*</bind>*/(i => i.P); } } "; var tree = Parse(text); var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree }); var model = comp.GetSemanticModel(tree); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, exprSyntaxToBind.Kind()); var bindInfo = model.GetSymbolInfo(exprSyntaxToBind); Assert.Equal("System.Collections.Generic.IEnumerable<System.Object> System.Collections.Generic.IEnumerable<T>.Select<T, System.Object>(System.Func<T, System.Object> selector)", bindInfo.Symbol.ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup1() { var types = @" public interface IA { object P { get; } } "; var members = LookupTypeParameterMembers(types, "IA", "P", out _); Assert.Equal("System.Object IA.P { get; }", members.Single().ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup2() { var types = @" public interface IA { object P { get; } } public interface IB { object P { get; } } "; ITypeParameterSymbol typeParameter; var members = LookupTypeParameterMembers(types, "IA, IB", "P", out typeParameter); Assert.True(members.SetEquals(typeParameter.AllEffectiveInterfacesNoUseSiteDiagnostics().Select(i => i.GetMember<IPropertySymbol>("P")))); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup3() { var types = @" public interface IA { object P { get; } } public interface IB : IA { new object P { get; } } "; var members = LookupTypeParameterMembers(types, "IA, IB", "P", out _); Assert.Equal("System.Object IB.P { get; }", members.Single().ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup4() { var types = @" public interface IA { object P { get; } } public class D { public object P { get; set; } } "; var members = LookupTypeParameterMembers(types, "D, IA", "P", out _); Assert.Equal("System.Object D.P { get; set; }", members.Single().ToTestDisplayString()); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup5() { var types = @" public interface IA { void M(); } public class D { public void M() { } } "; var members = LookupTypeParameterMembers(types, "IA", "M", out _); Assert.Equal("void IA.M()", members.Single().ToTestDisplayString()); members = LookupTypeParameterMembers(types, "D, IA", "M", out _); Assert.True(members.Select(m => m.ToTestDisplayString()).SetEquals(new[] { "void IA.M()", "void D.M()" })); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup6() { var types = @" public interface IA { void M(); void M(int x); } public class D { public void M() { } } "; var members = LookupTypeParameterMembers(types, "IA", "M", out _); Assert.True(members.Select(m => m.ToTestDisplayString()).SetEquals(new[] { "void IA.M()", "void IA.M(System.Int32 x)" })); members = LookupTypeParameterMembers(types, "D, IA", "M", out _); Assert.True(members.Select(m => m.ToTestDisplayString()).SetEquals(new[] { "void D.M()", "void IA.M()", "void IA.M(System.Int32 x)" })); } [WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")] [Fact] public void TypeParameterMemberLookup7() { var types = @" public interface IA { string ToString(); } public class D { public new string ToString() { return null; } } "; var members = LookupTypeParameterMembers(types, "IA", "ToString", out _); Assert.True(members.Select(m => m.ToTestDisplayString()).SetEquals(new[] { "System.String System.Object.ToString()", "System.String IA.ToString()" })); members = LookupTypeParameterMembers(types, "D, IA", "ToString", out _); Assert.True(members.Select(m => m.ToTestDisplayString()).SetEquals(new[] { "System.String System.Object.ToString()", "System.String D.ToString()", "System.String IA.ToString()" })); } private IEnumerable<ISymbol> LookupTypeParameterMembers(string types, string constraints, string memberName, out ITypeParameterSymbol typeParameter) { var template = @" {0} public class C<T> where T : {1} {{ void M() {{ System.Console.WriteLine(/*<bind>*/default(T)/*</bind>*/); }} }} "; var tree = Parse(string.Format(template, types, constraints)); var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(new[] { tree }); comp.VerifyDiagnostics(); var model = comp.GetSemanticModel(tree); var classC = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"); typeParameter = classC.TypeParameters.Single(); var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.DefaultExpression, exprSyntaxToBind.Kind()); return model.LookupSymbols(exprSyntaxToBind.SpanStart, typeParameter, memberName); } [WorkItem(542966, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542966")] [Fact] public async Task IndexerMemberRaceAsync() { var text = @" using System; interface IA { [System.Runtime.CompilerServices.IndexerName(""Goo"")] string this[int index] { get; } } class A : IA { public virtual string this[int index] { get { return """"; } } string IA.this[int index] { get { return """"; } } } class B : A, IA { public override string this[int index] { get { return """"; } } } class Program { public static void Main(string[] args) { IA x = new B(); Console.WriteLine(x[0]); } } "; TimeSpan timeout = TimeSpan.FromSeconds(2); for (int i = 0; i < 20; i++) { var comp = CreateCompilation(text); var task1 = new Task(() => comp.GlobalNamespace.GetMember<NamedTypeSymbol>("A").GetMembers()); var task2 = new Task(() => comp.GlobalNamespace.GetMember<NamedTypeSymbol>("IA").GetMembers()); if (i % 2 == 0) { task1.Start(); task2.Start(); } else { task2.Start(); task1.Start(); } comp.VerifyDiagnostics(); await Task.WhenAll(task1, task2); } } [Fact] public void ImplicitDeclarationMultipleDeclarators() { var text = @" using System.IO; class C { static void Main() { /*<bind>*/var a = new StreamWriter(""""), b = new StreamReader("""")/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); comp.VerifyDiagnostics( // (8,19): error CS0819: Implicitly-typed variables cannot have multiple declarators // /*<bind>*/var a = new StreamWriter(""), b = new StreamReader("")/*</bind>*/; Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableMultipleDeclarator, @"var a = new StreamWriter(""""), b = new StreamReader("""")").WithLocation(8, 19) ); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var typeInfo = model.GetSymbolInfo(expr); // the type info uses the type inferred for the first declared local Assert.Equal("System.IO.StreamWriter", typeInfo.Symbol.ToTestDisplayString()); } [WorkItem(543169, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543169")] [Fact] public void ParameterOfLambdaPassedToOutParameter() { var text = @" using System.Linq; class D { static void Main(string[] args) { string[] str = new string[] { }; label1: var s = str.Where(out /*<bind>*/x/*</bind>*/ => { return x == ""1""; }); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var lambdaSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().Single(); var parameterSymbol = model.GetDeclaredSymbol(lambdaSyntax.Parameter); Assert.NotNull(parameterSymbol); Assert.Equal("x", parameterSymbol.Name); Assert.Equal(MethodKind.AnonymousFunction, ((IMethodSymbol)parameterSymbol.ContainingSymbol).MethodKind); } [WorkItem(529096, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529096")] [Fact] public void MemberAccessExpressionResults() { var text = @" class C { public static int A; public static byte B() { return 3; } public static string D { get; set; } static void Main(string[] args) { /*<bind0>*/C.A/*</bind0>*/; /*<bind1>*/C.B/*</bind1>*/(); /*<bind2>*/C.D/*</bind2>*/; /*<bind3>*/C.B()/*</bind3>*/; int goo = /*<bind4>*/C.B()/*</bind4>*/; goo = /*<bind5>*/C.B/*</bind5>*/(); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var exprs = GetBindingNodes<ExpressionSyntax>(comp); for (int i = 0; i < exprs.Count; i++) { var expr = exprs[i]; var symbolInfo = model.GetSymbolInfo(expr); Assert.NotNull(symbolInfo.Symbol); var typeInfo = model.GetTypeInfo(expr); switch (i) { case 0: Assert.Equal("A", symbolInfo.Symbol.Name); Assert.NotNull(typeInfo.Type); Assert.Equal("System.Int32", typeInfo.Type.ToTestDisplayString()); Assert.Equal("System.Int32", typeInfo.ConvertedType.ToTestDisplayString()); break; case 1: case 5: Assert.Equal("B", symbolInfo.Symbol.Name); Assert.Null(typeInfo.Type); break; case 2: Assert.Equal("D", symbolInfo.Symbol.Name); Assert.NotNull(typeInfo.Type); Assert.Equal("System.String", typeInfo.Type.ToTestDisplayString()); Assert.Equal("System.String", typeInfo.ConvertedType.ToTestDisplayString()); break; case 3: Assert.Equal("B", symbolInfo.Symbol.Name); Assert.NotNull(typeInfo.Type); Assert.Equal("System.Byte", typeInfo.Type.ToTestDisplayString()); Assert.Equal("System.Byte", typeInfo.ConvertedType.ToTestDisplayString()); break; case 4: Assert.Equal("B", symbolInfo.Symbol.Name); Assert.NotNull(typeInfo.Type); Assert.Equal("System.Byte", typeInfo.Type.ToTestDisplayString()); Assert.Equal("System.Int32", typeInfo.ConvertedType.ToTestDisplayString()); break; } // switch } } [WorkItem(543554, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543554")] [Fact] public void SemanticInfoForUncheckedExpression() { var text = @" public class A { static void Main() { Console.WriteLine(/*<bind>*/unchecked(42 + 42.1)/*</bind>*/); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.Equal("System.Double System.Double.op_Addition(System.Double left, System.Double right)", sym.Symbol.ToTestDisplayString()); var info = model.GetTypeInfo(expr); var conv = model.GetConversion(expr); Assert.Equal(ConversionKind.Identity, conv.Kind); Assert.Equal(SpecialType.System_Double, info.Type.SpecialType); Assert.Equal(SpecialType.System_Double, info.ConvertedType.SpecialType); } [WorkItem(543554, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543554")] [Fact] public void SemanticInfoForCheckedExpression() { var text = @" class Program { public static int Add(int a, int b) { return /*<bind>*/checked(a+b)/*</bind>*/; } } "; var comp = CreateCompilation(text); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var sym = model.GetSymbolInfo(expr); Assert.Equal("System.Int32 System.Int32.op_CheckedAddition(System.Int32 left, System.Int32 right)", sym.Symbol.ToTestDisplayString()); var info = model.GetTypeInfo(expr); var conv = model.GetConversion(expr); Assert.Equal(ConversionKind.Identity, conv.Kind); Assert.Equal(SpecialType.System_Int32, info.Type.SpecialType); Assert.Equal(SpecialType.System_Int32, info.ConvertedType.SpecialType); } [WorkItem(543554, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543554")] [Fact] public void CheckedUncheckedExpression() { var text = @" class Test { public void F() { int y = /*<bind>*/(checked(unchecked((1))))/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var info = model.GetTypeInfo(expr); Assert.Equal(SpecialType.System_Int32, info.Type.SpecialType); Assert.Equal(SpecialType.System_Int32, info.ConvertedType.SpecialType); } [WorkItem(543543, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543543")] [Fact] public void SymbolInfoForImplicitOperatorParameter() { var text = @" class Program { public Program(string s) { } public static implicit operator Program(string str) { return new Program(/*<bind>*/str/*</bind>*/); } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var info = model.GetSymbolInfo(expr); var symbol = info.Symbol; Assert.NotNull(symbol); Assert.Equal(SymbolKind.Parameter, symbol.Kind); Assert.Equal(MethodKind.Conversion, ((IMethodSymbol)symbol.ContainingSymbol).MethodKind); } [WorkItem(543494, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543494")] [WorkItem(543560, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543560")] [Fact] public void BrokenPropertyDeclaration() { var source = @" using System; Class Program // this will get a Property declaration ... *sigh* { static void Main(string[] args) { Func<int, int> f = /*<bind0>*/x/*</bind0>*/ => x + 1; } } "; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var expr = tree.GetRoot().DescendantNodes().OfType<ParameterSyntax>().First(); var declaredSymbol = model.GetDeclaredSymbol(expr); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedBinaryOperator() { var text = @" class C { public static C operator+(C c1, C c2) { return c1 ?? c2; } static void Main() { C c1 = new C(); C c2 = new C(); C c3 = /*<bind>*/c1 + c2/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.AdditionOperatorName); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedLogicalOperator() { var text = @" class C { public static C operator &(C c1, C c2) { return c1 ?? c2; } public static bool operator true(C c) { return true; } public static bool operator false(C c) { return false; } static void Main() { C c1 = new C(); C c2 = new C(); C c3 = /*<bind>*/c1 && c2/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.BitwiseAndOperatorName); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedUnaryOperator() { var text = @" class C { public static C operator+(C c1) { return c1; } static void Main() { C c1 = new C(); C c2 = /*<bind>*/+c1/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.UnaryPlusOperatorName); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedExplicitConversion() { var text = @" class C { public static explicit operator C(int i) { return null; } static void Main() { C c1 = /*<bind>*/(C)1/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.ExplicitConversionName); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedImplicitConversion() { var text = @" class C { public static implicit operator C(int i) { return null; } static void Main() { C c1 = /*<bind>*/(C)1/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.ImplicitConversionName); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedTrueOperator() { var text = @" class C { public static bool operator true(C c) { return true; } public static bool operator false(C c) { return false; } static void Main() { C c = new C(); if (/*<bind>*/c/*</bind>*/) { } } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var type = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); var symbol = symbolInfo.Symbol; Assert.Equal(SymbolKind.Local, symbol.Kind); Assert.Equal("c", symbol.Name); Assert.Equal(type, ((ILocalSymbol)symbol).Type); var typeInfo = model.GetTypeInfo(expr); Assert.Equal(type, typeInfo.Type); Assert.Equal(type, typeInfo.ConvertedType); var conv = model.GetConversion(expr); Assert.Equal(Conversion.Identity, conv); Assert.False(model.GetConstantValue(expr).HasValue); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedIncrement() { var text = @" class C { public static C operator ++(C c) { return c; } static void Main() { C c1 = new C(); C c2 = /*<bind>*/c1++/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.IncrementOperatorName); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SemanticInfoForUserDefinedCompoundAssignment() { var text = @" class C { public static C operator +(C c1, C c2) { return c1 ?? c2; } static void Main() { C c1 = new C(); C c2 = new C(); /*<bind>*/c1 += c2/*</bind>*/; } } "; CheckOperatorSemanticInfo(text, WellKnownMemberNames.AdditionOperatorName); } private void CheckOperatorSemanticInfo(string text, string operatorName) { var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operatorSymbol = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IMethodSymbol>(operatorName); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal(operatorSymbol, symbolInfo.Symbol); var method = (IMethodSymbol)symbolInfo.Symbol; var returnType = method.ReturnType; var typeInfo = model.GetTypeInfo(expr); Assert.Equal(returnType, typeInfo.Type); Assert.Equal(returnType, typeInfo.ConvertedType); var conv = model.GetConversion(expr); Assert.Equal(ConversionKind.Identity, conv.Kind); Assert.False(model.GetConstantValue(expr).HasValue); } [Fact, WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550"), WorkItem(543439, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543439")] public void SymbolInfoForUserDefinedConversionOverloadResolutionFailure() { var text = @" struct S { public static explicit operator S(string s) { return default(S); } public static explicit operator S(System.Text.StringBuilder s) { return default(S); } static void Main() { S s = /*<bind>*/(S)null/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var conversions = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("S").GetMembers(WellKnownMemberNames.ExplicitConversionName); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(2, candidates.Length); Assert.True(candidates.SetEquals(conversions, EqualityComparer<ISymbol>.Default)); } [Fact, WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550"), WorkItem(543439, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543439")] public void SymbolInfoForUserDefinedConversionOverloadResolutionFailureEmpty() { var text = @" struct S { static void Main() { S s = /*<bind>*/(S)null/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var conversions = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("S").GetMembers(WellKnownMemberNames.ExplicitConversionName); Assert.Equal(0, conversions.Length); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(0, candidates.Length); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedUnaryOperatorOverloadResolutionFailure() { var il = @" .class public auto ansi beforefieldinit UnaryOperator extends [mscorlib]System.Object { .method public hidebysig specialname static class UnaryOperator op_UnaryPlus(class UnaryOperator unaryOperator) cil managed { ldnull throw } // Differs only by return type .method public hidebysig specialname static string op_UnaryPlus(class UnaryOperator unaryOperator) cil managed { ldnull throw } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ldarg.0 call instance void [mscorlib]System.Object::.ctor() ret } } "; var text = @" class Program { static void Main() { UnaryOperator u1 = new UnaryOperator(); UnaryOperator u2 = /*<bind>*/+u1/*</bind>*/; } } "; var comp = (Compilation)CreateCompilationWithILAndMscorlib40(text, il); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("UnaryOperator").GetMembers(WellKnownMemberNames.UnaryPlusOperatorName); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(2, candidates.Length); Assert.True(candidates.SetEquals(operators, EqualityComparer<ISymbol>.Default)); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedUnaryOperatorOverloadResolutionFailureEmpty() { var text = @" class C { static void Main() { C c1 = new C(); C c2 = /*<bind>*/+c1/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.UnaryPlusOperatorName); Assert.Equal(0, operators.Length); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(0, candidates.Length); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedIncrementOperatorOverloadResolutionFailure() { var il = @" .class public auto ansi beforefieldinit IncrementOperator extends [mscorlib]System.Object { .method public hidebysig specialname static class IncrementOperator op_Increment(class IncrementOperator incrementOperator) cil managed { ldnull throw } .method public hidebysig specialname static string op_Increment(class IncrementOperator incrementOperator) cil managed { ldnull throw } .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ldarg.0 call instance void [mscorlib]System.Object::.ctor() ret } } "; var text = @" class Program { static void Main() { IncrementOperator i1 = new IncrementOperator(); IncrementOperator i2 = /*<bind>*/i1++/*</bind>*/; } } "; var comp = (Compilation)CreateCompilationWithILAndMscorlib40(text, il); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("IncrementOperator").GetMembers(WellKnownMemberNames.IncrementOperatorName); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(2, candidates.Length); Assert.True(candidates.SetEquals(operators, EqualityComparer<ISymbol>.Default)); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedIncrementOperatorOverloadResolutionFailureEmpty() { var text = @" class C { static void Main() { C c1 = new C(); C c2 = /*<bind>*/c1++/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.IncrementOperatorName); Assert.Equal(0, operators.Length); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(0, candidates.Length); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedBinaryOperatorOverloadResolutionFailure() { var text = @" class C { public static C operator+(C c1, C c2) { return c1 ?? c2; } public static C operator+(C c1, string s) { return c1; } static void Main() { C c1 = new C(); C c2 = /*<bind>*/c1 + null/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.AdditionOperatorName); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(2, candidates.Length); Assert.True(candidates.SetEquals(operators, EqualityComparer<ISymbol>.Default)); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedBinaryOperatorOverloadResolutionFailureEmpty() { var text = @" class C { static void Main() { C c1 = new C(); C c2 = /*<bind>*/c1 + null/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.AdditionOperatorName); Assert.Equal(0, operators.Length); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal("System.String System.String.op_Addition(System.Object left, System.String right)", symbolInfo.Symbol.ToTestDisplayString()); Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(0, candidates.Length); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedCompoundAssignmentOperatorOverloadResolutionFailure() { var text = @" class C { public static C operator+(C c1, C c2) { return c1 ?? c2; } public static C operator+(C c1, string s) { return c1; } static void Main() { C c = new C(); /*<bind>*/c += null/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.AdditionOperatorName); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Null(symbolInfo.Symbol); Assert.Equal(CandidateReason.Ambiguous, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(2, candidates.Length); Assert.True(candidates.SetEquals(operators, EqualityComparer<ISymbol>.Default)); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550")] [Fact] public void SymbolInfoForUserDefinedCompoundAssignmentOperatorOverloadResolutionFailureEmpty() { var text = @" class C { static void Main() { C c = new C(); /*<bind>*/c += null/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.AdditionOperatorName); Assert.Equal(0, operators.Length); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal("System.String System.String.op_Addition(System.Object left, System.String right)", symbolInfo.Symbol.ToTestDisplayString()); Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); var candidates = symbolInfo.CandidateSymbols; Assert.Equal(0, candidates.Length); } [WorkItem(543550, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543550"), WorkItem(529158, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529158")] [Fact] public void MethodGroupForUserDefinedBinaryOperator() { var text = @" class C { public static C operator+(C c1, C c2) { return c1 ?? c2; } public static C operator+(C c1, int i) { return c1; } static void Main() { C c1 = new C(); C c2 = new C(); C c3 = /*<bind>*/c1 + c2/*</bind>*/; } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var operators = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMembers(WellKnownMemberNames.AdditionOperatorName).Cast<IMethodSymbol>(); var operatorSymbol = operators.Where(method => method.Parameters[0].Type.Equals(method.Parameters[1].Type, SymbolEqualityComparer.ConsiderEverything)).Single(); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal(operatorSymbol, symbolInfo.Symbol); // NOTE: This check captures, rather than enforces, the current behavior (i.e. feel free to change it). var memberGroup = model.GetMemberGroup(expr); Assert.Equal(0, memberGroup.Length); } [Fact] public void CacheDuplicates() { var text = @" class C { static void Main() { long l = /*<bind>*/(long)1/*</bind>*/; } } "; var tree = Parse(text); var comp = CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); bool sawWrongConversionKind = false; ThreadStart ts = () => sawWrongConversionKind |= ConversionKind.Identity != model.GetConversion(expr).Kind; Thread[] threads = new Thread[4]; for (int i = 0; i < threads.Length; i++) { threads[i] = new Thread(ts); } foreach (Thread t in threads) { t.Start(); } foreach (Thread t in threads) { t.Join(); } Assert.False(sawWrongConversionKind); } [WorkItem(543674, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543674")] [Fact()] public void SemanticInfo_NormalVsLiftedUserDefinedImplicitConversion() { string text = @" using System; struct G { } struct L { public static implicit operator G(L l) { return default(G); } } class Z { public static void Main() { MNG(/*<bind>*/default(L)/*</bind>*/); } static void MNG(G? g) { } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var gType = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("G"); var mngMethod = (IMethodSymbol)comp.GlobalNamespace.GetMember<INamedTypeSymbol>("Z").GetMembers("MNG").First(); var gNullableType = mngMethod.GetParameterType(0); Assert.True(gNullableType.IsNullableType(), "MNG parameter is not a nullable type?"); Assert.Equal(gType, gNullableType.StrippedType()); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var conversion = model.ClassifyConversion(expr, gNullableType); CheckIsAssignableTo(model, expr); // Here we have a situation where Roslyn deliberately violates the specification in order // to be compatible with the native compiler. // // The specification states that there are two applicable candidates: We can use // the "lifted" operator from L? to G?, or we can use the unlifted operator // from L to G, and then convert the G that comes out the back end to G?. // The specification says that the second conversion is the better conversion. // Therefore, the conversion on the "front end" should be an identity conversion, // and the conversion on the "back end" of the user-defined conversion should // be an implicit nullable conversion. // // This is not at all what the native compiler does, and we match the native // compiler behavior. The native compiler says that there is a "half lifted" // conversion from L-->G?, and that this is the winner. Therefore the conversion // "on the back end" of the user-defined conversion is in fact an *identity* // conversion, even though obviously we are going to have to // do code generation as though it was an implicit nullable conversion. Assert.Equal(ConversionKind.Identity, conversion.UserDefinedFromConversion.Kind); Assert.Equal(ConversionKind.Identity, conversion.UserDefinedToConversion.Kind); Assert.Equal("ImplicitUserDefined", conversion.ToString()); } [WorkItem(543715, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543715")] [Fact] public void SemanticInfo_NormalVsLiftedUserDefinedConversion_ImplicitConversion() { string text = @" using System; struct G {} struct M { public static implicit operator G(M m) { System.Console.WriteLine(1); return default(G); } public static implicit operator G(M? m) {System.Console.WriteLine(2); return default(G); } } class Z { public static void Main() { M? m = new M(); MNG(/*<bind>*/m/*</bind>*/); } static void MNG(G? g) { } } "; var tree = Parse(text); var comp = (Compilation)CreateCompilation(tree); var model = comp.GetSemanticModel(tree); var gType = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("G"); var mngMethod = (IMethodSymbol)comp.GlobalNamespace.GetMember<INamedTypeSymbol>("Z").GetMembers("MNG").First(); var gNullableType = mngMethod.GetParameterType(0); Assert.True(gNullableType.IsNullableType(), "MNG parameter is not a nullable type?"); Assert.Equal(gType, gNullableType.StrippedType()); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var conversion = model.ClassifyConversion(expr, gNullableType); CheckIsAssignableTo(model, expr); Assert.Equal(ConversionKind.ImplicitUserDefined, conversion.Kind); // Dev10 violates the spec for finding the most specific operator for an implicit user-defined conversion. // SPEC: • Find the most specific conversion operator: // SPEC: (a) If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator. // SPEC: (b) Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator. // SPEC: (c) Otherwise, the conversion is ambiguous and a compile-time error occurs. // In this test we try to classify conversion from M? to G?. // 1) Classify conversion establishes that SX: M? and TX: G?. // 2) Most specific conversion operator from M? to G?: // (a) does not hold here as neither of the implicit operators convert from M? to G? // (b) does hold here as the lifted form of "implicit operator G(M m)" converts from M? to G? // Hence "operator G(M m)" must be chosen in lifted form, but Dev10 chooses "G M.op_Implicit(System.Nullable<M> m)" in normal form. // We may want to maintain compatibility with Dev10. Assert.Equal("G M.op_Implicit(M? m)", conversion.MethodSymbol.ToTestDisplayString()); Assert.Equal("ImplicitUserDefined", conversion.ToString()); } [Fact] public void AmbiguousImplicitConversionOverloadResolution1() { var source = @" public class A { static public implicit operator A(B b) { return default(A); } } public class B { static public implicit operator A(B b) { return default(A); } } class Test { static void M(A a) { } static void M(object o) { } static void Main() { B b = new B(); /*<bind>*/M(b)/*</bind>*/; } }"; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics( // (26,21): error CS0457: Ambiguous user defined conversions 'B.implicit operator A(B)' and 'A.implicit operator A(B)' when converting from 'B' to 'A' Diagnostic(ErrorCode.ERR_AmbigUDConv, "b").WithArguments("B.implicit operator A(B)", "A.implicit operator A(B)", "B", "A")); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var expr = (InvocationExpressionSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal("void Test.M(A a)", symbolInfo.Symbol.ToTestDisplayString()); var argexpr = expr.ArgumentList.Arguments.Single().Expression; var argTypeInfo = model.GetTypeInfo(argexpr); Assert.Equal("B", argTypeInfo.Type.ToTestDisplayString()); Assert.Equal("A", argTypeInfo.ConvertedType.ToTestDisplayString()); var argConversion = model.GetConversion(argexpr); Assert.Equal(ConversionKind.ImplicitUserDefined, argConversion.Kind); Assert.False(argConversion.IsValid); Assert.Null(argConversion.Method); } [Fact] public void AmbiguousImplicitConversionOverloadResolution2() { var source = @" public class A { static public implicit operator A(B<A> b) { return default(A); } } public class B<T> { static public implicit operator T(B<T> b) { return default(T); } } class C { static void M(A a) { } static void M<T>(T t) { } static void Main() { B<A> b = new B<A>(); /*<bind>*/M(b)/*</bind>*/; } }"; var compilation = CreateCompilation(source); compilation.VerifyDiagnostics(); // since no conversion is performed, the ambiguity doesn't matter var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var expr = (InvocationExpressionSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.NotNull(expr); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal("void C.M<B<A>>(B<A> t)", symbolInfo.Symbol.ToTestDisplayString()); var argexpr = expr.ArgumentList.Arguments.Single().Expression; var argTypeInfo = model.GetTypeInfo(argexpr); Assert.Equal("B<A>", argTypeInfo.Type.ToTestDisplayString()); Assert.Equal("B<A>", argTypeInfo.ConvertedType.ToTestDisplayString()); var argConversion = model.GetConversion(argexpr); Assert.Equal(ConversionKind.Identity, argConversion.Kind); Assert.True(argConversion.IsValid); Assert.Null(argConversion.Method); } [Fact] public void DefaultParameterLocalScope() { var source = @" public class A { static void Main(string[] args, int a = /*<bind>*/System/*</bind>*/.) { } }"; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal("System", expr.ToString()); var info = model.GetSemanticInfoSummary(expr); //Shouldn't throw/assert Assert.Equal(SymbolKind.Namespace, info.Symbol.Kind); } [Fact] public void PinvokeSemanticModel() { var source = @" using System; using System.Runtime.InteropServices; class C { [DllImport(""user32.dll"", CharSet = CharSet.Unicode, ExactSpelling = false, EntryPoint = ""MessageBox"")] public static extern int MessageBox(IntPtr hwnd, string t, string c, UInt32 t2); static void Main() { /*<bind>*/MessageBox(IntPtr.Zero, """", """", 1)/*</bind>*/; } }"; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var expr = (InvocationExpressionSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal("MessageBox(IntPtr.Zero, \"\", \"\", 1)", expr.ToString()); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal("C.MessageBox(System.IntPtr, string, string, uint)", symbolInfo.Symbol.ToDisplayString()); var argTypeInfo = model.GetTypeInfo(expr.ArgumentList.Arguments.First().Expression); Assert.Equal("System.IntPtr", argTypeInfo.Type.ToTestDisplayString()); Assert.Equal("System.IntPtr", argTypeInfo.ConvertedType.ToTestDisplayString()); } [Fact] public void ImplicitBoxingConversion1() { var source = @" class C { static void Main() { object o = 1; } }"; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var literal = tree.GetCompilationUnitRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Single(); var literalTypeInfo = model.GetTypeInfo(literal); var conv = model.GetConversion(literal); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Object, literalTypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Boxing, conv.Kind); } [Fact] public void ImplicitBoxingConversion2() { var source = @" class C { static void Main() { object o = (long)1; } }"; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var literal = tree.GetCompilationUnitRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Single(); var literalTypeInfo = model.GetTypeInfo(literal); var literalConversion = model.GetConversion(literal); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, literalConversion.Kind); var cast = (CastExpressionSyntax)literal.Parent; var castTypeInfo = model.GetTypeInfo(cast); var castConversion = model.GetConversion(cast); Assert.Equal(SpecialType.System_Int64, castTypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Object, castTypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Boxing, castConversion.Kind); } [Fact] public void ExplicitBoxingConversion1() { var source = @" class C { static void Main() { object o = (object)1; } }"; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var literal = tree.GetCompilationUnitRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Single(); var literalTypeInfo = model.GetTypeInfo(literal); var literalConversion = model.GetConversion(literal); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, literalConversion.Kind); var cast = (CastExpressionSyntax)literal.Parent; var castTypeInfo = model.GetTypeInfo(cast); var castConversion = model.GetConversion(cast); Assert.Equal(SpecialType.System_Object, castTypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Object, castTypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, castConversion.Kind); Assert.Equal(ConversionKind.Boxing, model.ClassifyConversion(literal, castTypeInfo.Type).Kind); CheckIsAssignableTo(model, literal); } [Fact] public void ExplicitBoxingConversion2() { var source = @" class C { static void Main() { object o = (object)(long)1; } }"; var compilation = CreateCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var literal = tree.GetCompilationUnitRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Single(); var literalTypeInfo = model.GetTypeInfo(literal); var literalConversion = model.GetConversion(literal); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Int32, literalTypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, literalConversion.Kind); var cast1 = (CastExpressionSyntax)literal.Parent; var cast1TypeInfo = model.GetTypeInfo(cast1); var cast1Conversion = model.GetConversion(cast1); Assert.Equal(SpecialType.System_Int64, cast1TypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Int64, cast1TypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, cast1Conversion.Kind); // Note that this reflects the hypothetical conversion, not the cast in the code. Assert.Equal(ConversionKind.ImplicitNumeric, model.ClassifyConversion(literal, cast1TypeInfo.Type).Kind); CheckIsAssignableTo(model, literal); var cast2 = (CastExpressionSyntax)cast1.Parent; var cast2TypeInfo = model.GetTypeInfo(cast2); var cast2Conversion = model.GetConversion(cast2); Assert.Equal(SpecialType.System_Object, cast2TypeInfo.Type.SpecialType); Assert.Equal(SpecialType.System_Object, cast2TypeInfo.ConvertedType.SpecialType); Assert.Equal(ConversionKind.Identity, cast2Conversion.Kind); Assert.Equal(ConversionKind.Boxing, model.ClassifyConversion(cast1, cast2TypeInfo.Type).Kind); CheckIsAssignableTo(model, cast1); } [WorkItem(545136, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545136")] [WorkItem(538320, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538320")] [Fact()] // TODO: Dev10 does not report ERR_SameFullNameAggAgg here - source wins. public void SpecialTypeInSourceAndMetadata() { var text = @" using System; namespace System { public struct Void { static void Main() { System./*<bind>*/Void/*</bind>*/.Equals(1, 1); } } } "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var expr = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal("System.Void", symbolInfo.Symbol.ToString()); Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason); Assert.Equal(0, symbolInfo.CandidateSymbols.Length); } [WorkItem(544651, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544651")] [Fact] public void SpeculativelyBindMethodGroup1() { var text = @" using System; class C { static void M() { int here; } } "; var compilation = (Compilation)CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = text.IndexOf("here", StringComparison.Ordinal); var syntax = SyntaxFactory.ParseExpression(" C.M"); //Leading trivia was significant for triggering an assert before the fix. Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind()); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); Assert.Equal(compilation.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IMethodSymbol>("M"), info.CandidateSymbols.Single()); Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); } [WorkItem(544651, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544651")] [Fact] public void SpeculativelyBindMethodGroup2() { var text = @" using System; class C { static void M() { int here; } static void M(int x) { } } "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = text.IndexOf("here", StringComparison.Ordinal); var syntax = SyntaxFactory.ParseExpression(" C.M"); //Leading trivia was significant for triggering an assert before the fix. Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind()); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); Assert.Null(info.Symbol); Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); Assert.Equal(2, info.CandidateSymbols.Length); } [WorkItem(546046, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546046")] [Fact] public void UnambiguousMethodGroupWithoutBoundParent1() { var text = @" using System; class C { static void M() { /*<bind>*/M/*</bind>*/ "; var compilation = (Compilation)CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, syntax.Kind()); var info = model.GetSymbolInfo(syntax); Assert.Equal(compilation.GlobalNamespace.GetMember<INamedTypeSymbol>("C").GetMember<IMethodSymbol>("M"), info.CandidateSymbols.Single()); Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); } [WorkItem(546046, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546046")] [Fact] public void UnambiguousMethodGroupWithoutBoundParent2() { var text = @" using System; class C { static void M() { /*<bind>*/M/*</bind>*/[] "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.IdentifierName, syntax.Kind()); var info = model.GetSymbolInfo(syntax); Assert.Null(info.Symbol); Assert.Equal(CandidateReason.NotATypeOrNamespace, info.CandidateReason); Assert.Equal(1, info.CandidateSymbols.Length); } [WorkItem(544651, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544651")] [ClrOnlyFact] public void SpeculativelyBindPropertyGroup1() { var source1 = @"Imports System.Runtime.InteropServices <Assembly: PrimaryInteropAssembly(0, 0)> <Assembly: Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E210"")> <ComImport()> <Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E211"")> Public Interface IA Property P(o As Object) As Object End Interface"; var reference1 = BasicCompilationUtils.CompileToMetadata(source1); var source2 = @" using System; class C { static void M(IA a) { int here; } } "; var compilation = (Compilation)CreateCompilation(source2, new[] { reference1 }, assemblyName: "SpeculativelyBindPropertyGroup"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = source2.IndexOf("here", StringComparison.Ordinal); var syntax = SyntaxFactory.ParseExpression(" a.P"); //Leading trivia was significant for triggering an assert before the fix. Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind()); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); Assert.Equal(compilation.GlobalNamespace.GetMember<INamedTypeSymbol>("IA").GetMember<IPropertySymbol>("P"), info.Symbol); } [WorkItem(544651, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544651")] [ClrOnlyFact] public void SpeculativelyBindPropertyGroup2() { var source1 = @"Imports System.Runtime.InteropServices <Assembly: PrimaryInteropAssembly(0, 0)> <Assembly: Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E210"")> <ComImport()> <Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E211"")> Public Interface IA Property P(o As Object) As Object Property P(x As Object, y As Object) As Object End Interface"; var reference1 = BasicCompilationUtils.CompileToMetadata(source1); var source2 = @" using System; class C { static void M(IA a) { int here; } } "; var compilation = CreateCompilation(source2, new[] { reference1 }, assemblyName: "SpeculativelyBindPropertyGroup"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = source2.IndexOf("here", StringComparison.Ordinal); var syntax = SyntaxFactory.ParseExpression(" a.P"); //Leading trivia was significant for triggering an assert before the fix. Assert.Equal(SyntaxKind.SimpleMemberAccessExpression, syntax.Kind()); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); Assert.Null(info.Symbol); Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); Assert.Equal(2, info.CandidateSymbols.Length); } // There is no test analogous to UnambiguousMethodGroupWithoutBoundParent1 because // a.P does not yield a bound property group - it yields a bound indexer access // (i.e. it doesn't actually hit the code path that formerly contained the assert). //[WorkItem(15177)] //[Fact] //public void UnambiguousPropertyGroupWithoutBoundParent1() [WorkItem(546117, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546117")] [ClrOnlyFact] public void UnambiguousPropertyGroupWithoutBoundParent2() { var source1 = @"Imports System.Runtime.InteropServices <Assembly: PrimaryInteropAssembly(0, 0)> <Assembly: Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E210"")> <ComImport()> <Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E211"")> Public Interface IA Property P(o As Object) As Object End Interface"; var reference1 = BasicCompilationUtils.CompileToMetadata(source1); var source2 = @" using System; class C { static void M(IA a) { /*<bind>*/a.P/*</bind>*/[] "; var compilation = CreateCompilation(source2, new[] { reference1 }, assemblyName: "SpeculativelyBindPropertyGroup"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.QualifiedName, syntax.Kind()); var info = model.GetSymbolInfo(syntax); Assert.Null(info.Symbol); Assert.Equal(CandidateReason.NotATypeOrNamespace, info.CandidateReason); Assert.Equal(1, info.CandidateSymbols.Length); } [WorkItem(544648, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544648")] [Fact] public void SpeculativelyBindExtensionMethod() { var source = @" using System; using System.Collections.Generic; using System.Reflection; static class Program { static void Main() { FieldInfo[] fields = typeof(Exception).GetFields(); Console.WriteLine(/*<bind>*/fields.Any((Func<FieldInfo, bool>)(field => field.IsStatic))/*</bind>*/); } static bool Any<T>(this IEnumerable<T> s, Func<T, bool> predicate) { return false; } static bool Any<T>(this ICollection<T> s, Func<T, bool> predicate) { return true; } } "; var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var originalSyntax = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); Assert.Equal(SyntaxKind.InvocationExpression, originalSyntax.Kind()); var info1 = model.GetSymbolInfo(originalSyntax); var method1 = info1.Symbol as IMethodSymbol; Assert.NotNull(method1); Assert.Equal("System.Boolean System.Collections.Generic.ICollection<System.Reflection.FieldInfo>.Any<System.Reflection.FieldInfo>(System.Func<System.Reflection.FieldInfo, System.Boolean> predicate)", method1.ToTestDisplayString()); Assert.Same(method1.ReducedFrom.TypeParameters[0], method1.TypeParameters[0].ReducedFrom); Assert.Null(method1.ReducedFrom.TypeParameters[0].ReducedFrom); Assert.Equal("System.Boolean Program.Any<T>(this System.Collections.Generic.ICollection<T> s, System.Func<T, System.Boolean> predicate)", method1.ReducedFrom.ToTestDisplayString()); Assert.Equal("System.Collections.Generic.ICollection<System.Reflection.FieldInfo>", method1.ReceiverType.ToTestDisplayString()); Assert.Equal("System.Reflection.FieldInfo", method1.GetTypeInferredDuringReduction(method1.ReducedFrom.TypeParameters[0]).ToTestDisplayString()); Assert.Throws<InvalidOperationException>(() => method1.ReducedFrom.GetTypeInferredDuringReduction(null)); Assert.Throws<ArgumentNullException>(() => method1.GetTypeInferredDuringReduction(null)); Assert.Throws<ArgumentException>(() => method1.GetTypeInferredDuringReduction( comp.Assembly.GlobalNamespace.GetMember<INamedTypeSymbol>("Program").GetMembers("Any"). Where((m) => (object)m != (object)method1.ReducedFrom).Cast<IMethodSymbol>().Single().TypeParameters[0])); Assert.Equal("Any", method1.Name); var reducedFrom1 = method1.GetSymbol().CallsiteReducedFromMethod; Assert.NotNull(reducedFrom1); Assert.Equal("System.Boolean Program.Any<System.Reflection.FieldInfo>(this System.Collections.Generic.ICollection<System.Reflection.FieldInfo> s, System.Func<System.Reflection.FieldInfo, System.Boolean> predicate)", reducedFrom1.ToTestDisplayString()); Assert.Equal("Program", reducedFrom1.ReceiverType.ToTestDisplayString()); Assert.Equal(SpecialType.System_Collections_Generic_ICollection_T, ((TypeSymbol)reducedFrom1.Parameters[0].Type.OriginalDefinition).SpecialType); var speculativeSyntax = SyntaxFactory.ParseExpression("fields.Any((field => field.IsStatic))"); //cast removed Assert.Equal(SyntaxKind.InvocationExpression, speculativeSyntax.Kind()); var info2 = model.GetSpeculativeSymbolInfo(originalSyntax.SpanStart, speculativeSyntax, SpeculativeBindingOption.BindAsExpression); var method2 = info2.Symbol as IMethodSymbol; Assert.NotNull(method2); Assert.Equal("Any", method2.Name); var reducedFrom2 = method2.GetSymbol().CallsiteReducedFromMethod; Assert.NotNull(reducedFrom2); Assert.Equal(SpecialType.System_Collections_Generic_ICollection_T, ((TypeSymbol)reducedFrom2.Parameters[0].Type.OriginalDefinition).SpecialType); Assert.Equal(reducedFrom1, reducedFrom2); Assert.Equal(method1, method2); } /// <summary> /// This test reproduces the issue we were seeing in DevDiv #13366: LocalSymbol.SetType was asserting /// because it was set to IEnumerable<int> before binding the declaration of x but to an error /// type after binding the declaration of x. /// </summary> [WorkItem(545097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545097")] [Fact] public void NameConflictDuringLambdaBinding1() { var source = @" using System.Linq; class C { static void Main() { var x = 0; var q = from e in """" let x = 2 select x; } } "; var comp = CreateCompilationWithMscorlib40AndSystemCore(source); var tree = comp.SyntaxTrees.Single(); var localDecls = tree.GetCompilationUnitRoot().DescendantNodes().OfType<VariableDeclarationSyntax>(); var localDecl1 = localDecls.First(); Assert.Equal("x", localDecl1.Variables.Single().Identifier.ValueText); var localDecl2 = localDecls.Last(); Assert.Equal("q", localDecl2.Variables.Single().Identifier.ValueText); var model = comp.GetSemanticModel(tree); var info0 = model.GetSymbolInfo(localDecl2.Type); Assert.Equal(SpecialType.System_Collections_Generic_IEnumerable_T, ((ITypeSymbol)info0.Symbol.OriginalDefinition).SpecialType); Assert.Equal(SpecialType.System_Int32, ((INamedTypeSymbol)info0.Symbol).TypeArguments.Single().SpecialType); var info1 = model.GetSymbolInfo(localDecl1.Type); Assert.Equal(SpecialType.System_Int32, ((ITypeSymbol)info1.Symbol).SpecialType); // This used to assert because the second binding would see the declaration of x and report CS7040, disrupting the delegate conversion. var info2 = model.GetSymbolInfo(localDecl2.Type); Assert.Equal(SpecialType.System_Collections_Generic_IEnumerable_T, ((ITypeSymbol)info2.Symbol.OriginalDefinition).SpecialType); Assert.Equal(SpecialType.System_Int32, ((INamedTypeSymbol)info2.Symbol).TypeArguments.Single().SpecialType); comp.VerifyDiagnostics( // (9,34): error CS1931: The range variable 'x' conflicts with a previous declaration of 'x' // var q = from e in "" let x = 2 select x; Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "x").WithArguments("x").WithLocation(9, 34), // (8,13): warning CS0219: The variable 'x' is assigned but its value is never used // var x = 0; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(8, 13) ); } /// <summary> /// This test reverses the order of statement binding from NameConflictDuringLambdaBinding2 to confirm that /// the results are the same. /// </summary> [WorkItem(545097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545097")] [Fact] public void NameConflictDuringLambdaBinding2() { var source = @" using System.Linq; class C { static void Main() { var x = 0; var q = from e in """" let x = 2 select x; } } "; var comp = CreateCompilationWithMscorlib40AndSystemCore(source); var tree = comp.SyntaxTrees.Single(); var localDecls = tree.GetCompilationUnitRoot().DescendantNodes().OfType<VariableDeclarationSyntax>(); var localDecl1 = localDecls.First(); Assert.Equal("x", localDecl1.Variables.Single().Identifier.ValueText); var localDecl2 = localDecls.Last(); Assert.Equal("q", localDecl2.Variables.Single().Identifier.ValueText); var model = comp.GetSemanticModel(tree); var info1 = model.GetSymbolInfo(localDecl1.Type); Assert.Equal(SpecialType.System_Int32, ((ITypeSymbol)info1.Symbol).SpecialType); // This used to assert because the second binding would see the declaration of x and report CS7040, disrupting the delegate conversion. var info2 = model.GetSymbolInfo(localDecl2.Type); Assert.Equal(SpecialType.System_Collections_Generic_IEnumerable_T, ((ITypeSymbol)info2.Symbol.OriginalDefinition).SpecialType); Assert.Equal(SpecialType.System_Int32, ((INamedTypeSymbol)info2.Symbol).TypeArguments.Single().SpecialType); comp.VerifyDiagnostics( // (9,34): error CS1931: The range variable 'x' conflicts with a previous declaration of 'x' // var q = from e in "" let x = 2 select x; Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "x").WithArguments("x").WithLocation(9, 34), // (8,13): warning CS0219: The variable 'x' is assigned but its value is never used // var x = 0; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(8, 13) ); } [WorkItem(546263, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546263")] [Fact] public void SpeculativeSymbolInfoForOmittedTypeArgumentSyntaxNode() { var text = @"namespace N2 { using N1; class Test { class N1<G1> {} static void Main() { int res = 0; N1<int> n1 = new N1<int>(); global::N1 < > .C1 c1 = null; } } }"; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = text.IndexOf("< >", StringComparison.Ordinal); var syntax = tree.GetCompilationUnitRoot().FindToken(position).Parent.DescendantNodesAndSelf().OfType<OmittedTypeArgumentSyntax>().Single(); var info = model.GetSpeculativeSymbolInfo(syntax.SpanStart, syntax, SpeculativeBindingOption.BindAsTypeOrNamespace); Assert.Null(info.Symbol); } [WorkItem(530313, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530313")] [Fact] public void SpeculativeTypeInfoForOmittedTypeArgumentSyntaxNode() { var text = @"namespace N2 { using N1; class Test { class N1<G1> {} static void Main() { int res = 0; N1<int> n1 = new N1<int>(); global::N1 < > .C1 c1 = null; } } }"; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = text.IndexOf("< >", StringComparison.Ordinal); var syntax = tree.GetCompilationUnitRoot().FindToken(position).Parent.DescendantNodesAndSelf().OfType<OmittedTypeArgumentSyntax>().Single(); var info = model.GetSpeculativeTypeInfo(syntax.SpanStart, syntax, SpeculativeBindingOption.BindAsTypeOrNamespace); Assert.Equal(TypeInfo.None, info); } [WorkItem(546266, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546266")] [Fact] public void SpeculativeTypeInfoForGenericNameSyntaxWithinTypeOfInsideAnonMethod() { var text = @" delegate void Del(); class C { public void M1() { Del d = delegate () { var v1 = typeof(S<,,,>); }; } } "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = text.IndexOf("S<,,,>", StringComparison.Ordinal); var syntax = tree.GetCompilationUnitRoot().FindToken(position).Parent.DescendantNodesAndSelf().OfType<GenericNameSyntax>().Single(); var info = model.GetSpeculativeTypeInfo(syntax.SpanStart, syntax, SpeculativeBindingOption.BindAsTypeOrNamespace); Assert.NotNull(info.Type); } [WorkItem(547160, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547160")] [Fact, WorkItem(531496, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531496")] public void SemanticInfoForOmittedTypeArgumentInIncompleteMember() { var text = @" class Test { C<> "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<OmittedTypeArgumentSyntax>().Single(); var info = model.GetSemanticInfoSummary(syntax); Assert.Null(info.Alias); Assert.Equal(CandidateReason.None, info.CandidateReason); Assert.True(info.CandidateSymbols.IsEmpty); Assert.False(info.ConstantValue.HasValue); Assert.Null(info.ConvertedType); Assert.Equal(Conversion.Identity, info.ImplicitConversion); Assert.False(info.IsCompileTimeConstant); Assert.True(info.MemberGroup.IsEmpty); Assert.True(info.MethodGroup.IsEmpty); Assert.Null(info.Symbol); Assert.Null(info.Type); } [WorkItem(547160, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547160")] [Fact, WorkItem(531496, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531496")] public void CollectionInitializerSpeculativeInfo() { var text = @" class Test { } "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var speculativeSyntax = SyntaxFactory.ParseExpression("new List { 1, 2 }"); var initializerSyntax = speculativeSyntax.DescendantNodesAndSelf().OfType<InitializerExpressionSyntax>().Single(); var symbolInfo = model.GetSpeculativeSymbolInfo(0, initializerSyntax, SpeculativeBindingOption.BindAsExpression); Assert.Equal(SymbolInfo.None, symbolInfo); var typeInfo = model.GetSpeculativeTypeInfo(0, initializerSyntax, SpeculativeBindingOption.BindAsExpression); Assert.Equal(TypeInfo.None, typeInfo); } [WorkItem(531362, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531362")] [Fact] public void DelegateElementAccess() { var text = @" class C { void M(bool b) { System.Action o = delegate { if (b) { } } [1]; } } "; var compilation = CreateCompilation(text); compilation.VerifyDiagnostics( // (6,27): error CS0021: Cannot apply indexing with [] to an expression of type 'anonymous method' // System.Action o = delegate { if (b) { } } [1]; Diagnostic(ErrorCode.ERR_BadIndexLHS, "delegate { if (b) { } } [1]").WithArguments("anonymous method")); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Last(id => id.Identifier.ValueText == "b"); var info = model.GetSymbolInfo(syntax); } [Fact] public void EnumBitwiseComplement() { var text = @" using System; enum Color { Red, Green, Blue } class C { static void Main() { Func<Color, Color> f2 = x => /*<bind>*/~x/*</bind>*/; } }"; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = GetExprSyntaxForBinding(GetExprSyntaxList(tree)); var info = model.GetTypeInfo(syntax); var conv = model.GetConversion(syntax); Assert.Equal(TypeKind.Enum, info.Type.TypeKind); Assert.Equal(ConversionKind.Identity, conv.Kind); } [WorkItem(531534, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531534")] [Fact] public void LambdaOutsideMemberModel() { var text = @" int P { badAccessorName { M(env => env); "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().Last(); var symbol = model.GetDeclaredSymbol(syntax); // Doesn't assert. Assert.Null(symbol); } [WorkItem(633340, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/633340")] [Fact] public void MemberOfInaccessibleType() { var text = @" class A { private class Nested { public class Another { } } } public class B : A { public Nested.Another a; } "; var compilation = (Compilation)CreateCompilation(text); var global = compilation.GlobalNamespace; var classA = global.GetMember<INamedTypeSymbol>("A"); var classNested = classA.GetMember<INamedTypeSymbol>("Nested"); var classAnother = classNested.GetMember<INamedTypeSymbol>("Another"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var fieldSyntax = tree.GetRoot().DescendantNodes().OfType<FieldDeclarationSyntax>().Single(); var qualifiedSyntax = (QualifiedNameSyntax)fieldSyntax.Declaration.Type; var leftSyntax = qualifiedSyntax.Left; var rightSyntax = qualifiedSyntax.Right; var leftInfo = model.GetSymbolInfo(leftSyntax); Assert.Equal(CandidateReason.Inaccessible, leftInfo.CandidateReason); Assert.Equal(classNested, leftInfo.CandidateSymbols.Single()); var rightInfo = model.GetSymbolInfo(rightSyntax); Assert.Equal(CandidateReason.Inaccessible, rightInfo.CandidateReason); Assert.Equal(classAnother, rightInfo.CandidateSymbols.Single()); compilation.VerifyDiagnostics( // (12,14): error CS0060: Inconsistent accessibility: base type 'A' is less accessible than class 'B' // public class B : A Diagnostic(ErrorCode.ERR_BadVisBaseClass, "B").WithArguments("B", "A"), // (14,12): error CS0122: 'A.Nested' is inaccessible due to its protection level // public Nested.Another a; Diagnostic(ErrorCode.ERR_BadAccess, "Nested").WithArguments("A.Nested")); } [WorkItem(633340, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/633340")] [Fact] public void NotReferencableMemberOfInaccessibleType() { var text = @" class A { private class Nested { public int P { get; set; } } } class B : A { int Test(Nested nested) { return nested.get_P(); } } "; var compilation = (Compilation)CreateCompilation(text); var global = compilation.GlobalNamespace; var classA = global.GetMember<INamedTypeSymbol>("A"); var classNested = classA.GetMember<INamedTypeSymbol>("Nested"); var propertyP = classNested.GetMember<IPropertySymbol>("P"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var memberAccessSyntax = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().Single(); var info = model.GetSymbolInfo(memberAccessSyntax); Assert.Equal(CandidateReason.NotReferencable, info.CandidateReason); Assert.Equal(propertyP.GetMethod, info.CandidateSymbols.Single()); compilation.VerifyDiagnostics( // (12,14): error CS0122: 'A.Nested' is inaccessible due to its protection level // int Test(Nested nested) Diagnostic(ErrorCode.ERR_BadAccess, "Nested").WithArguments("A.Nested"), // (14,23): error CS0571: 'A.Nested.P.get': cannot explicitly call operator or accessor // return nested.get_P(); Diagnostic(ErrorCode.ERR_CantCallSpecialMethod, "get_P").WithArguments("A.Nested.P.get") ); } [WorkItem(633340, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/633340")] [Fact] public void AccessibleMemberOfInaccessibleType() { var text = @" public class A { private class Nested { } } public class B : A { void Test() { Nested.ReferenceEquals(null, null); // Actually object.ReferenceEquals. } } "; var compilation = (Compilation)CreateCompilation(text); var global = compilation.GlobalNamespace; var classA = global.GetMember<INamedTypeSymbol>("A"); var classNested = classA.GetMember<INamedTypeSymbol>("Nested"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var callSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single(); var methodAccessSyntax = (MemberAccessExpressionSyntax)callSyntax.Expression; var nestedTypeAccessSyntax = methodAccessSyntax.Expression; var typeInfo = model.GetSymbolInfo(nestedTypeAccessSyntax); Assert.Equal(CandidateReason.Inaccessible, typeInfo.CandidateReason); Assert.Equal(classNested, typeInfo.CandidateSymbols.Single()); var methodInfo = model.GetSymbolInfo(callSyntax); Assert.Equal(compilation.GetSpecialTypeMember(SpecialMember.System_Object__ReferenceEquals), methodInfo.Symbol); compilation.VerifyDiagnostics( // (13,9): error CS0122: 'A.Nested' is inaccessible due to its protection level // Nested.ReferenceEquals(null, null); // Actually object.ReferenceEquals. Diagnostic(ErrorCode.ERR_BadAccess, "Nested").WithArguments("A.Nested")); } [WorkItem(530252, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530252")] [Fact] public void MethodGroupHiddenSymbols1() { var text = @" class C { public override int GetHashCode() { return 0; } } struct S { public override int GetHashCode() { return 0; } } class Test { int M(C c) { return c.GetHashCode } int M(S s) { return s.GetHashCode } } "; var compilation = CreateCompilation(text); var global = compilation.GlobalNamespace; var classType = global.GetMember<NamedTypeSymbol>("C"); var structType = global.GetMember<NamedTypeSymbol>("S"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var memberAccesses = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().ToArray(); Assert.Equal(2, memberAccesses.Length); var classMemberAccess = memberAccesses[0]; var structMemberAccess = memberAccesses[1]; var classInfo = model.GetSymbolInfo(classMemberAccess); var structInfo = model.GetSymbolInfo(structMemberAccess); // Only one candidate. Assert.Equal(CandidateReason.OverloadResolutionFailure, classInfo.CandidateReason); Assert.Equal("System.Int32 C.GetHashCode()", classInfo.CandidateSymbols.Single().ToTestDisplayString()); Assert.Equal(CandidateReason.OverloadResolutionFailure, structInfo.CandidateReason); Assert.Equal("System.Int32 S.GetHashCode()", structInfo.CandidateSymbols.Single().ToTestDisplayString()); } [WorkItem(530252, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530252")] [Fact] public void MethodGroupHiddenSymbols2() { var text = @" class A { public virtual void M() { } } class B : A { public override void M() { } } class C : B { public override void M() { } } class Program { static void Main(string[] args) { C c = new C(); c.M } } "; var compilation = CreateCompilation(text); var classC = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var memberAccess = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().Single(); var info = model.GetSymbolInfo(memberAccess); // Only one candidate. Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason); Assert.Equal("void C.M()", info.CandidateSymbols.Single().ToTestDisplayString()); } [Fact] [WorkItem(645512, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/645512")] public void LookupProtectedMemberOnConstrainedTypeParameter() { var source = @" class A { protected void Goo() { } } class C : A { public void Bar<T>(T t, C c) where T : C { t.Goo(); c.Goo(); } } "; var comp = (Compilation)CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); comp.VerifyDiagnostics(); var global = comp.GlobalNamespace; var classA = global.GetMember<INamedTypeSymbol>("A"); var methodGoo = classA.GetMember<IMethodSymbol>("Goo"); var classC = global.GetMember<INamedTypeSymbol>("C"); var methodBar = classC.GetMember<IMethodSymbol>("Bar"); var paramType0 = methodBar.GetParameterType(0); Assert.Equal(TypeKind.TypeParameter, paramType0.TypeKind); var paramType1 = methodBar.GetParameterType(1); Assert.Equal(TypeKind.Class, paramType1.TypeKind); int position = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().First().SpanStart; Assert.Contains("Goo", model.LookupNames(position, paramType0)); Assert.Contains("Goo", model.LookupNames(position, paramType1)); } [Fact] [WorkItem(645512, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/645512")] public void LookupProtectedMemberOnConstrainedTypeParameter2() { var source = @" class A { protected void Goo() { } } class C : A { public void Bar<T, U>(T t, C c) where T : U where U : C { t.Goo(); c.Goo(); } } "; var comp = (Compilation)CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); comp.VerifyDiagnostics(); var global = comp.GlobalNamespace; var classA = global.GetMember<INamedTypeSymbol>("A"); var methodGoo = classA.GetMember<IMethodSymbol>("Goo"); var classC = global.GetMember<INamedTypeSymbol>("C"); var methodBar = classC.GetMember<IMethodSymbol>("Bar"); var paramType0 = methodBar.GetParameterType(0); Assert.Equal(TypeKind.TypeParameter, paramType0.TypeKind); var paramType1 = methodBar.GetParameterType(1); Assert.Equal(TypeKind.Class, paramType1.TypeKind); int position = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().First().SpanStart; Assert.Contains("Goo", model.LookupNames(position, paramType0)); Assert.Contains("Goo", model.LookupNames(position, paramType1)); } [Fact] [WorkItem(652583, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/652583")] public void ParameterDefaultValueWithoutParameter() { var source = @" class A { protected void Goo(bool b, = true "; var comp = CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var trueLiteral = tree.GetRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Single(); Assert.Equal(SyntaxKind.TrueLiteralExpression, trueLiteral.Kind()); model.GetSymbolInfo(trueLiteral); var parameterSyntax = trueLiteral.FirstAncestorOrSelf<ParameterSyntax>(); Assert.Equal(SyntaxKind.Parameter, parameterSyntax.Kind()); model.GetDeclaredSymbol(parameterSyntax); } [Fact] [WorkItem(530791, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530791")] public void Repro530791() { var source = @" class Program { static void Main(string[] args) { Test test = new Test(() => { return null; }); } } class Test { } "; var comp = CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var lambdaSyntax = tree.GetRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single(); var symbolInfo = model.GetSymbolInfo(lambdaSyntax); var lambda = (IMethodSymbol)symbolInfo.Symbol; Assert.False(lambda.ReturnsVoid); Assert.Equal(SymbolKind.ErrorType, lambda.ReturnType.Kind); } [Fact] public void InvocationInLocalDeclarationInLambdaInConstructorInitializer() { var source = @" using System; public class C { public int M() { return null; } } public class Test { public Test() : this(c => { int i = c.M(); return i; }) { } public Test(Func<C, int> f) { } } "; var comp = CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var syntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single(); var symbolInfo = model.GetSymbolInfo(syntax); var methodSymbol = (IMethodSymbol)symbolInfo.Symbol; Assert.False(methodSymbol.ReturnsVoid); } [Fact] [WorkItem(654753, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/654753")] public void Repro654753() { var source = @" using System; using System.Collections.Generic; using System.Linq; public class C { private readonly C Instance = new C(); bool M(IDisposable d) { using(d) { bool any = this.Instance.GetList().OfType<D>().Any(); return any; } } IEnumerable<C> GetList() { return null; } } public class D : C { } "; var comp = CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var position = source.IndexOf("this", StringComparison.Ordinal); var statement = tree.GetRoot().DescendantNodes().OfType<LocalDeclarationStatementSyntax>().Single(); var newSyntax = SyntaxFactory.ParseExpression("Instance.GetList().OfType<D>().Any()"); var newStatement = statement.ReplaceNode(statement.Declaration.Variables[0].Initializer.Value, newSyntax); newSyntax = newStatement.Declaration.Variables[0].Initializer.Value; SemanticModel speculativeModel; bool success = model.TryGetSpeculativeSemanticModel(position, newStatement, out speculativeModel); Assert.True(success); Assert.NotNull(speculativeModel); var newSyntaxMemberAccess = newSyntax.DescendantNodesAndSelf().OfType<MemberAccessExpressionSyntax>(). Single(e => e.ToString() == "Instance.GetList().OfType<D>"); speculativeModel.GetTypeInfo(newSyntaxMemberAccess); } [Fact] [WorkItem(750557, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/750557")] public void MethodGroupFromMetadata() { var source = @" class Goo { delegate int D(int i); void M() { var v = ((D)(x => x)).Equals is bool; } } "; var comp = CreateCompilationWithMscorlib40AndSystemCore(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var position = source.IndexOf("Equals", StringComparison.Ordinal); var equalsToken = tree.GetRoot().FindToken(position); var equalsNode = equalsToken.Parent; var symbolInfo = model.GetSymbolInfo(equalsNode); //note that we don't guarantee what symbol will come back on a method group in an is expression. Assert.Null(symbolInfo.Symbol); Assert.True(symbolInfo.CandidateSymbols.Length > 0); Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason); } [Fact, WorkItem(531304, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531304")] public void GetPreprocessingSymbolInfoForDefinedSymbol() { string sourceCode = @" #define X #if X //bind #define Z #endif #if Z //bind #endif // broken code cases #define A #if A + 1 //bind #endif #define B = 0 #if B //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "X //bind"); Assert.Equal("X", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "A + 1 //bind"); Assert.Equal("A", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "B //bind"); Assert.Equal("B", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); Assert.True(symbolInfo.Symbol.Equals(symbolInfo.Symbol)); Assert.False(symbolInfo.Symbol.Equals(null)); PreprocessingSymbolInfo symbolInfo2 = GetPreprocessingSymbolInfoForTest(sourceCode, "B //bind"); Assert.NotSame(symbolInfo.Symbol, symbolInfo2.Symbol); Assert.Equal(symbolInfo.Symbol, symbolInfo2.Symbol); Assert.Equal(symbolInfo.Symbol.GetHashCode(), symbolInfo2.Symbol.GetHashCode()); } [Fact, WorkItem(531304, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531304")] public void GetPreprocessingSymbolInfoForUndefinedSymbol() { string sourceCode = @" #define X #undef X #if X //bind #endif #if x //bind #endif #if Y //bind #define Z #endif #if Z //bind #endif // Not in preprocessor trivia #define A public class T { public int Goo(int A) { return A; //bind } } "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "X //bind"); Assert.Equal("X", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "x //bind"); Assert.Equal("x", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Y //bind"); Assert.Equal("Y", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "A; //bind"); Assert.Null(symbolInfo.Symbol); } [Fact, WorkItem(531304, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531304"), WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void GetPreprocessingSymbolInfoForSymbolDefinedLaterInSource() { string sourceCode = @" #if Z //bind #endif #define Z "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(72907, "https://github.com/dotnet/roslyn/issues/72907")] public void GetPreprocessingSymbolInfoOnUnrelatedDirective() { const string sourceCode = """ #pragma warning disable Z //bind pragma warning disable """; var symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind pragma warning disable"); Assert.Null(symbolInfo.Symbol); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_01() { string sourceCode = @" #define Z #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_02() { string sourceCode = @" #if true #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_03() { string sourceCode = @" #if false #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_04() { string sourceCode = @" #if true #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_05() { string sourceCode = @" #if false #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_06() { string sourceCode = @" #if true #else #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_07() { string sourceCode = @" #if false #else #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_08() { string sourceCode = @" #if true #define Z #else #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_09() { string sourceCode = @" #if false #define Z #else #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_10() { string sourceCode = @" #if true #elif true #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_11() { string sourceCode = @" #if false #elif true #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_12() { string sourceCode = @" #if false #elif false #define Z #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_13() { string sourceCode = @" #if true #define Z #elif false #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_14() { string sourceCode = @" #if true #define Z #elif true #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_15() { string sourceCode = @" #if false #define Z #elif true #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_16() { string sourceCode = @" #if false #define Z #elif false #if Z //bind #endif #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_17() { string sourceCode = @" #if false #else #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_18() { string sourceCode = @" #if false #elif true #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.True(symbolInfo.IsDefined, "must be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_19() { string sourceCode = @" #if true #else #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_20() { string sourceCode = @" #if true #elif true #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_21() { string sourceCode = @" #if true #elif false #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [Fact, WorkItem(720566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/720566")] public void Bug720566_22() { string sourceCode = @" #if false #elif false #define Z #endif #if Z //bind #endif "; PreprocessingSymbolInfo symbolInfo = GetPreprocessingSymbolInfoForTest(sourceCode, "Z //bind"); Assert.Equal("Z", symbolInfo.Symbol.Name); Assert.False(symbolInfo.IsDefined, "must not be defined"); } [WorkItem(835391, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/835391")] [Fact] public void ConstructedErrorTypeValidation() { var text = @"class C1 : E1 { } class C2<T> : E2<T> { }"; var compilation = (Compilation)CreateCompilation(text); var objectType = compilation.GetSpecialType(SpecialType.System_Object); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var root = tree.GetCompilationUnitRoot(); // Non-generic type. var type = (INamedTypeSymbol)model.GetDeclaredSymbol(root.Members[0]); Assert.False(type.IsGenericType); Assert.False(type.IsErrorType()); Assert.Throws<InvalidOperationException>(() => type.Construct(objectType)); // non-generic type // Non-generic error type. type = type.BaseType; Assert.False(type.IsGenericType); Assert.True(type.IsErrorType()); Assert.Throws<InvalidOperationException>(() => type.Construct(objectType)); // non-generic type // Generic type. type = (INamedTypeSymbol)model.GetDeclaredSymbol(root.Members[1]); Assert.True(type.IsGenericType); Assert.False(type.IsErrorType()); Assert.Throws<ArgumentException>(() => type.Construct(new ITypeSymbol[] { null })); // null type arg Assert.Throws<ArgumentException>(() => type.Construct()); // typeArgs.Length != Arity Assert.Throws<InvalidOperationException>(() => type.Construct(objectType).Construct(objectType)); // constructed type // Generic error type. type = type.BaseType.ConstructedFrom; Assert.True(type.IsGenericType); Assert.True(type.IsErrorType()); Assert.Throws<ArgumentException>(() => type.Construct(new ITypeSymbol[] { null })); // null type arg Assert.Throws<ArgumentException>(() => type.Construct()); // typeArgs.Length != Arity Assert.Throws<InvalidOperationException>(() => type.Construct(objectType).Construct(objectType)); // constructed type } [Fact] [WorkItem(849371, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/849371")] public void NestedLambdaErrorRecovery() { var source = @" using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; class Program { static void Main() { Task<IEnumerable<Task<A>>> teta = null; teta.ContinueWith(tasks => { var list = tasks.Result.Select(t => X(t.Result)); // Wrong argument type for X. list.ToString(); }); } static B X(int x) { return null; } class A { } class B { } } "; for (int i = 0; i < 10; i++) // Ten runs to ensure consistency. { var comp = CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics( // (13,51): error CS1503: Argument 1: cannot convert from 'Program.A' to 'int' // var list = tasks.Result.Select(t => X(t.Result)); // Wrong argument type for X. Diagnostic(ErrorCode.ERR_BadArgType, "t.Result").WithArguments("1", "Program.A", "int").WithLocation(13, 51), // (13,30): error CS1061: 'System.Threading.Tasks.Task' does not contain a definition for 'Result' and no extension method 'Result' accepting a first argument of type 'System.Threading.Tasks.Task' could be found (are you missing a using directive or an assembly reference?) // var list = tasks.Result.Select(t => X(t.Result)); // Wrong argument type for X. Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Result").WithArguments("System.Threading.Tasks.Task", "Result").WithLocation(13, 30)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var invocationSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().First(); var invocationInfo = model.GetSymbolInfo(invocationSyntax); Assert.Equal(CandidateReason.OverloadResolutionFailure, invocationInfo.CandidateReason); Assert.Null(invocationInfo.Symbol); Assert.NotEqual(0, invocationInfo.CandidateSymbols.Length); var parameterSyntax = invocationSyntax.DescendantNodes().OfType<ParameterSyntax>().First(); var parameterSymbol = model.GetDeclaredSymbol(parameterSyntax); Assert.Equal("System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<Program.A>>>", parameterSymbol.Type.ToTestDisplayString()); } } [WorkItem(849371, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/849371")] [WorkItem(854543, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854543")] [WorkItem(854548, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854548")] [Fact] public void SemanticModelLambdaErrorRecovery() { var source = @" using System; class Program { static void Main() { M(() => 1); // Neither overload wins. } static void M(Func<string> a) { } static void M(Func<char> a) { } } "; { var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var lambdaSyntax = tree.GetRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single(); var otherFuncType = comp.GetWellKnownType(WellKnownType.System_Func_T).Construct(comp.GetSpecialType(SpecialType.System_Int32)); var typeInfo = model.GetTypeInfo(lambdaSyntax); Assert.Null(typeInfo.Type); Assert.NotEqual(otherFuncType, typeInfo.ConvertedType); } { var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var lambdaSyntax = tree.GetRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single(); var otherFuncType = comp.GetWellKnownType(WellKnownType.System_Func_T).Construct(comp.GetSpecialType(SpecialType.System_Int32)); var conversion = model.ClassifyConversion(lambdaSyntax, otherFuncType); CheckIsAssignableTo(model, lambdaSyntax); var typeInfo = model.GetTypeInfo(lambdaSyntax); Assert.Null(typeInfo.Type); Assert.NotEqual(otherFuncType, typeInfo.ConvertedType); // Not affected by call to ClassifyConversion. } } [Fact] [WorkItem(854543, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854543")] public void ClassifyConversionOnNull() { var source = @" class Program { static void Main() { M(null); // Ambiguous. } static void M(A a) { } static void M(B b) { } } class A { } class B { } class C { } "; var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics( // (6,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.M(A)' and 'Program.M(B)' // M(null); // Ambiguous. Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("Program.M(A)", "Program.M(B)").WithLocation(6, 9)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var nullSyntax = tree.GetRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().Single(); var typeC = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"); var conversion = model.ClassifyConversion(nullSyntax, typeC); CheckIsAssignableTo(model, nullSyntax); Assert.Equal(ConversionKind.ImplicitReference, conversion.Kind); } [WorkItem(854543, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854543")] [Fact] public void ClassifyConversionOnLambda() { var source = @" using System; class Program { static void Main() { M(() => null); } static void M(Func<A> a) { } } class A { } class B { } "; var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var lambdaSyntax = tree.GetRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single(); var typeB = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("B"); var typeFuncB = comp.GetWellKnownType(WellKnownType.System_Func_T).Construct(typeB); var conversion = model.ClassifyConversion(lambdaSyntax, typeFuncB); CheckIsAssignableTo(model, lambdaSyntax); Assert.Equal(ConversionKind.AnonymousFunction, conversion.Kind); } [WorkItem(854543, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854543")] [Fact] public void ClassifyConversionOnAmbiguousLambda() { var source = @" using System; class Program { static void Main() { M(() => null); // Ambiguous. } static void M(Func<A> a) { } static void M(Func<B> b) { } } class A { } class B { } class C { } "; var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics( // (8,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.M(System.Func<A>)' and 'Program.M(System.Func<B>)' // M(() => null); // Ambiguous. Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("Program.M(System.Func<A>)", "Program.M(System.Func<B>)").WithLocation(8, 9)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var lambdaSyntax = tree.GetRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Single(); var typeC = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"); var typeFuncC = comp.GetWellKnownType(WellKnownType.System_Func_T).Construct(typeC); var conversion = model.ClassifyConversion(lambdaSyntax, typeFuncC); CheckIsAssignableTo(model, lambdaSyntax); Assert.Equal(ConversionKind.AnonymousFunction, conversion.Kind); } [WorkItem(854543, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854543")] [Fact] public void ClassifyConversionOnAmbiguousMethodGroup() { var source = @" using System; class Base<T> { public A N(T t) { throw null; } public B N(int t) { throw null; } } class Derived : Base<int> { void Test() { M(N); // Ambiguous. } static void M(Func<int, A> a) { } static void M(Func<int, B> b) { } } class A { } class B { } class C { } "; var comp = (Compilation)CreateCompilationWithMscorlib40AndSystemCore(source); comp.VerifyDiagnostics( // (14,9): error CS0121: The call is ambiguous between the following methods or properties: 'Derived.M(System.Func<int, A>)' and 'Derived.M(System.Func<int, B>)' // M(N); // Ambiguous. Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("Derived.M(System.Func<int, A>)", "Derived.M(System.Func<int, B>)").WithLocation(14, 9)); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var methodGroupSyntax = tree.GetRoot().DescendantNodes().OfType<ArgumentSyntax>().Single().Expression; var global = comp.GlobalNamespace; var typeA = global.GetMember<INamedTypeSymbol>("A"); var typeB = global.GetMember<INamedTypeSymbol>("B"); var typeC = global.GetMember<INamedTypeSymbol>("C"); var typeInt = comp.GetSpecialType(SpecialType.System_Int32); var typeFunc = comp.GetWellKnownType(WellKnownType.System_Func_T2); var typeFuncA = typeFunc.Construct(typeInt, typeA); var typeFuncB = typeFunc.Construct(typeInt, typeB); var typeFuncC = typeFunc.Construct(typeInt, typeC); var conversionA = model.ClassifyConversion(methodGroupSyntax, typeFuncA); CheckIsAssignableTo(model, methodGroupSyntax); Assert.Equal(ConversionKind.MethodGroup, conversionA.Kind); var conversionB = model.ClassifyConversion(methodGroupSyntax, typeFuncB); Assert.Equal(ConversionKind.MethodGroup, conversionB.Kind); var conversionC = model.ClassifyConversion(methodGroupSyntax, typeFuncC); Assert.Equal(ConversionKind.NoConversion, conversionC.Kind); } [WorkItem(872064, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/872064")] [Fact] public void PartialMethodImplementationDiagnostics() { var file1 = @" namespace ConsoleApplication1 { class Program { static void Main(string[] args) { } } partial class MyPartialClass { partial void MyPartialMethod(MyUndefinedMethod m); } } "; var file2 = @" namespace ConsoleApplication1 { partial class MyPartialClass { partial void MyPartialMethod(MyUndefinedMethod m) { c = new MyUndefinedMethod(23, true); } } } "; var tree1 = Parse(file1); var tree2 = Parse(file2); var comp = CreateCompilation(new[] { tree1, tree2 }); var model = comp.GetSemanticModel(tree2); var errs = model.GetDiagnostics(); Assert.Equal(3, errs.Count()); errs = model.GetSyntaxDiagnostics(); Assert.Equal(0, errs.Count()); errs = model.GetDeclarationDiagnostics(); Assert.Equal(1, errs.Count()); errs = model.GetMethodBodyDiagnostics(); Assert.Equal(2, errs.Count()); } [Fact] public void PartialTypeDiagnostics_StaticConstructors() { var file1 = @" partial class C { static C() {} } "; var file2 = @" partial class C { static C() {} } "; var file3 = @" partial class C { static C() {} } "; var tree1 = Parse(file1); var tree2 = Parse(file2); var tree3 = Parse(file3); var comp = CreateCompilation(new[] { tree1, tree2, tree3 }); var model1 = comp.GetSemanticModel(tree1); var model2 = comp.GetSemanticModel(tree2); var model3 = comp.GetSemanticModel(tree3); model1.GetDeclarationDiagnostics().Verify(); model2.GetDeclarationDiagnostics().Verify( // (4,12): error CS0111: Type 'C' already defines a member called 'C' with the same parameter types Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "C").WithArguments("C", "C").WithLocation(4, 12)); model3.GetDeclarationDiagnostics().Verify( // (4,12): error CS0111: Type 'C' already defines a member called 'C' with the same parameter types Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "C").WithArguments("C", "C").WithLocation(4, 12)); Assert.Equal(3, comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").StaticConstructors.Length); } [Fact] public void PartialTypeDiagnostics_Constructors() { var file1 = @" partial class C { C() {} } "; var file2 = @" partial class C { C() {} } "; var file3 = @" partial class C { C() {} } "; var tree1 = Parse(file1); var tree2 = Parse(file2); var tree3 = Parse(file3); var comp = CreateCompilation(new[] { tree1, tree2, tree3 }); var model1 = comp.GetSemanticModel(tree1); var model2 = comp.GetSemanticModel(tree2); var model3 = comp.GetSemanticModel(tree3); model1.GetDeclarationDiagnostics().Verify(); model2.GetDeclarationDiagnostics().Verify( // (4,5): error CS0111: Type 'C' already defines a member called 'C' with the same parameter types Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "C").WithArguments("C", "C").WithLocation(4, 5)); model3.GetDeclarationDiagnostics().Verify( // (4,5): error CS0111: Type 'C' already defines a member called 'C' with the same parameter types Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "C").WithArguments("C", "C").WithLocation(4, 5)); Assert.Equal(3, comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").InstanceConstructors.Length); } [WorkItem(1076661, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1076661")] [Fact] public void Bug1076661() { const string source = @" using X = System.Collections.Generic.List<dynamic>; class Test { void Goo(ref X. x) { } }"; var comp = CreateCompilation(source); var diag = comp.GetDiagnostics(); } [Fact] public void QueryClauseInBadStatement_Catch() { var source = @"using System; class C { static void F(object[] c) { catch (Exception) when (from o in c where true) { } } }"; var comp = CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var tokens = tree.GetCompilationUnitRoot().DescendantTokens(); var expr = tokens.Single(t => t.Kind() == SyntaxKind.TrueKeyword).Parent; Assert.Null(model.GetSymbolInfo(expr).Symbol); Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(expr).Type.SpecialType); } [Fact] public void GetSpecialType_ThrowsOnLessThanZero() { var source = "class C1 { }"; var comp = CreateCompilation(source); var specialType = (SpecialType)(-1); var exceptionThrown = false; try { comp.GetSpecialType(specialType); } catch (ArgumentOutOfRangeException e) { exceptionThrown = true; Assert.StartsWith(expectedStartString: $"Unexpected SpecialType: '{(int)specialType}'.", actualString: e.Message); } Assert.True(exceptionThrown, $"{nameof(comp.GetSpecialType)} did not throw when it should have."); } [Fact] public void GetSpecialType_ThrowsOnGreaterThanCount() { var source = "class C1 { }"; var comp = (Compilation)CreateCompilation(source); var specialType = SpecialType.Count + 1; var exceptionThrown = false; try { comp.GetSpecialType(specialType); } catch (ArgumentOutOfRangeException e) { exceptionThrown = true; Assert.StartsWith(expectedStartString: $"Unexpected SpecialType: '{(int)specialType}'.", actualString: e.Message); } Assert.True(exceptionThrown, $"{nameof(comp.GetSpecialType)} did not throw when it should have."); } [Fact] [WorkItem(34984, "https://github.com/dotnet/roslyn/issues/34984")] public void ConversionIsExplicit_UnsetConversionKind() { var source = @"class C1 { } class C2 { public void M() { var c = new C1(); foreach (string item in c.Items) { } }"; var comp = CreateCompilation(source); var tree = comp.SyntaxTrees.Single(); var model = comp.GetSemanticModel(tree); var root = tree.GetRoot(); var foreachSyntaxNode = root.DescendantNodes().OfType<ForEachStatementSyntax>().Single(); var foreachSymbolInfo = model.GetForEachStatementInfo(foreachSyntaxNode); Assert.Equal(Conversion.UnsetConversion, foreachSymbolInfo.CurrentConversion); Assert.True(foreachSymbolInfo.CurrentConversion.Exists); Assert.False(foreachSymbolInfo.CurrentConversion.IsImplicit); } [Fact, WorkItem(29933, "https://github.com/dotnet/roslyn/issues/29933")] public void SpeculativelyBindBaseInXmlDoc() { var text = @" class C { /// <summary> </summary> static void M() { } } "; var compilation = CreateCompilation(text); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var position = text.IndexOf(">", StringComparison.Ordinal); var syntax = SyntaxFactory.ParseExpression("base"); var info = model.GetSpeculativeSymbolInfo(position, syntax, SpeculativeBindingOption.BindAsExpression); Assert.Null(info.Symbol); Assert.Equal(CandidateReason.NotReferencable, info.CandidateReason); } [Fact] [WorkItem(42840, "https://github.com/dotnet/roslyn/issues/42840")] public void DuplicateTypeArgument() { var source = @"class A<T> { } class B<T, U, U> where T : A<U> where U : class { }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (4,15): error CS0692: Duplicate type parameter 'U' // class B<T, U, U> Diagnostic(ErrorCode.ERR_DuplicateTypeParameter, "U").WithArguments("U").WithLocation(4, 15), // (5,17): error CS0229: Ambiguity between 'U' and 'U' // where T : A<U> Diagnostic(ErrorCode.ERR_AmbigMember, "U").WithArguments("U", "U").WithLocation(5, 17)); comp = CreateCompilation(source); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var typeParameters = tree.GetRoot().DescendantNodes().OfType<TypeParameterSyntax>().ToArray(); var symbol = model.GetDeclaredSymbol(typeParameters[typeParameters.Length - 1]); Assert.False(symbol.IsReferenceType); symbol = model.GetDeclaredSymbol(typeParameters[typeParameters.Length - 2]); Assert.True(symbol.IsReferenceType); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75570")] public void GetConstructedReducedFrom_WithNullableInferredType() { var source = """ #nullable enable using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; class C1 { } class C2 { } class D { public static void ConvertAll(IEnumerable<C1> values) { var v = values.Select(Convert); } [return: NotNullIfNotNull(nameof(value))] private static C2? Convert(C1? value) => value is null ? null : new C2(); } """ + NotNullIfNotNullAttributeDefinition; var comp = CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var memberAccess = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().First(); var constructedMethodSymbol = (IMethodSymbol)model.GetSymbolInfo(memberAccess).Symbol; // Ensure that both the bound reduced method symbol, and the constructed method symbol // it was reduced from both have the right nullable annotations for the type parameters. Assert.True(constructedMethodSymbol is { Name: nameof(Enumerable.Select), TypeArguments: [ { Name: "C1", NullableAnnotation: Microsoft.CodeAnalysis.NullableAnnotation.NotAnnotated }, { Name: "C2", NullableAnnotation: Microsoft.CodeAnalysis.NullableAnnotation.Annotated } ], ReceiverType.Name: nameof(IEnumerable<>), }); var constructedReducedFrom = constructedMethodSymbol.GetConstructedReducedFrom(); Assert.True(constructedReducedFrom is { Name: nameof(Enumerable.Select), TypeArguments: [ { Name: "C1", NullableAnnotation: Microsoft.CodeAnalysis.NullableAnnotation.NotAnnotated }, { Name: "C2", NullableAnnotation: Microsoft.CodeAnalysis.NullableAnnotation.Annotated } ], ReceiverType.Name: nameof(Enumerable), }); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79930")] public void NotInvoicableInvocationTarget() { var source = @" public class OuterClass { void M() { var s = OuterClass.InnerClass(); } public class InnerClass { } } "; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,28): error CS1955: Non-invocable member 'OuterClass.InnerClass' cannot be used like a method. // var s = OuterClass.InnerClass(); Diagnostic(ErrorCode.ERR_NonInvocableMemberCalled, "InnerClass").WithArguments("OuterClass.InnerClass").WithLocation(6, 28) ); var tree = comp.SyntaxTrees[0]; var semanticModel = comp.GetSemanticModel(tree); var invocationNode = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single(); var expressionNode = invocationNode.Expression; var info = semanticModel.GetSymbolInfo(expressionNode); Assert.Null(info.Symbol); Assert.Equal(CandidateReason.NotInvocable, info.CandidateReason); Assert.Same(comp.GetTypeByMetadataName("OuterClass+InnerClass").GetPublicSymbol(), info.CandidateSymbols.Single()); } } }