|
// 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 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 Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class MethodBodyModelTests : CSharpTestBase
{
[WorkItem(537881, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537881")]
[Fact]
public void BindAliasWithSameNameClass()
{
var text = @"
using NSA = A;
namespace A
{
class Goo { }
}
namespace B
{
class Test
{
class NSA
{
public NSA(int Goo) { this.Goo = Goo; }
int Goo;
}
static int Main()
{
NSA::Goo goo = new NSA::Goo(); // shouldn't error here
if (goo == null) {}
return 0;
}
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(0, comp.GetDeclarationDiagnostics().Count());
comp.GetMethodBodyDiagnostics().Verify();
}
[Fact, WorkItem(537919, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537919")]
public void NullRefForNameAndOptionalMethod()
{
var text = @"
public class MyClass
{
public object Method01(int x, int y = 0, int z = 1) { return null; }
public static void Main()
{
MyClass c = new MyClass();
c.Method01(999, z: 888);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(0, comp.GetDeclarationDiagnostics().Count());
comp.GetMethodBodyDiagnostics().Verify();
}
[WorkItem(538099, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538099")]
[Fact]
public void ConversionsForLiterals()
{
var text = @"
class Program
{
static void Main()
{
uint ui = 2;
goo(ui + 2);
}
static void goo(uint x)
{
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(538100, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538100")]
[Fact]
public void ConversionsFromVoid()
{
var text = @"
using System;
class Program
{
static void Main()
{
object x = goo();
if (x == null) {}
Console.WriteLine(goo());
}
static void goo()
{
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
int[] count = new int[4];
Dictionary<int, int> errors = new Dictionary<int, int>();
foreach (var e in comp.GetDiagnostics())
{
count[(int)e.Severity]++;
if (!errors.ContainsKey(e.Code)) errors[e.Code] = 0;
errors[e.Code] += 1;
}
Assert.Equal(2, count[(int)DiagnosticSeverity.Error]);
Assert.Equal(0, count[(int)DiagnosticSeverity.Warning]);
Assert.Equal(0, count[(int)DiagnosticSeverity.Info]);
Assert.Equal(1, errors[29]);
// Assert.Equal(1, errors[1502]);
Assert.Equal(1, errors[1503]);
}
[WorkItem(538110, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538110")]
[Fact]
public void NullComparisons()
{
var text = @"
using System;
class Program
{
static void Main()
{
bool x = (true == true);
object f = new object();
x = (f == null);
Console.WriteLine(x);
x = (null == f);
Console.WriteLine(x);
x = (null == null);
Console.WriteLine(x);
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(538114, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538114")]
[Fact]
public void OvldRslnWithExplicitIfaceImpl()
{
var text = @"
using System;
interface i1
{
int bar(int x);
}
class @c : i1
{
public int bar(int x)
{
Console.WriteLine(""1"");
return 0;
}
int i1.bar(int x)
{
Console.WriteLine(""2"");
return 1;
}
public void test()
{
this.bar(1);
}
}
class Program
{
static void Main()
{
c x = new c();
x.test();
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(3613, "DevDiv_Projects/Roslyn")]
[Fact]
public void OverloadResolutionCallThroughInterface()
{
var text = @"
using System;
public interface i1
{
float bar(string x);
int bar(int x);
}
class @c : i1
{
public int bar(int x)
{
Console.WriteLine(""1"");
return 0;
}
public float bar(string x)
{
Console.WriteLine(""2"");
return 0;
}
}
class Program
{
static void Main()
{
c x = new c();
i1 y = x;
int i = 1;
x.bar(i); // Works
y.bar(i); // Fails to resolve
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(538194, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538194")]
[Fact]
public void ComparisonOperatorForRefTypes()
{
var text = @"
class Program
{
static void Main()
{
object o = null; object o1 = null;
if(o == o1)
{
}
if(o != o1)
{
}
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(538211, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538211")]
[Fact]
public void BindCastConversionOnArithmeticOp()
{
var text = @"
public class MyClass
{
public static int Main()
{
int i1 = (int)(0x80000000 % -1);
if (i1 == 0)
{
return 0;
}
else
{
return 1;
}
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(538212, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538212")]
[Fact]
public void NegBindLHSCStyleArray()
{
// Expect CS0650 etc.
var text = @"
using System;
class Test
{
public static int Main()
{
int arr[] = new int[10];
return 0;
}
}
";
// The native compiler produces four errors for this: that the [] is in the wrong place
// is the correct error. It also produces three incorrect errors due to a faulty
// error recovery heuristic; it treats the '=' as a statement and the "new int[10];"
// as a statement, and therefore gives three additional errors: that there is
// a missing semicolon before and after the '=', and that '=' is not a valid statement.
// In Roslyn we now do error recovery better and treat the initialization clause
// as an initializer. We therefore expect one parse error, not four.
var tree = Parse(text);
Assert.Equal(1, tree.GetDiagnostics().Count());
Assert.Equal(650, tree.GetDiagnostics().First().Code);
}
// ImmutableArray NullRef exception by BoundTreeRewriter (No bug for now)
[Fact]
public void NegBindMultiDimArrayInit()
{
var text = @"
class A
{
public static int Main()
{
int[,] arr = new int[3,2] {{1,2},,{4,5}};
return 0;
}
}
";
CreateCompilation(text).VerifyDiagnostics(
// (6,42): error CS1525: Invalid expression term ','
// int[,] arr = new int[3,2] {{1,2},,{4,5}};
Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",")
);
}
[Fact]
public void MethodGroupToDelegate01()
{
var text = @"
delegate bool IntFunc(int x);
delegate bool LongFunc(long x);
public class Program
{
static bool F(long l) { return false; }
static bool F(int i) { return true; }
public static void Main(string[] args)
{
IntFunc intFunc = F;
LongFunc longFunc = F;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[Fact]
public void MethodGroupToDelegate02()
{
var text = @"
public class Program2
{
delegate void MyAction<T>(T x);
void Y(int x) { }
void D(MyAction<int> o) { }
void D(MyAction<long> o) { }
void T()
{
D(Y);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[Fact]
public void MethodGroupToDelegate03()
{
var text = @"
public class Program1
{
delegate void MyAction<T>(T x);
void Y(long x) { }
void D(MyAction<int> o) { }
void T()
{
D(Y); // wrong parameter type
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(1, comp.GetDiagnostics().Count());
}
[Fact]
public void MethodGroupToDelegate04()
{
var text = @"
public class Program1
{
delegate void MyAction<T>(T x);
void Y(long x) { }
void D(MyAction<int> o) { }
void D(MyAction<long> o) { }
void T()
{
D(Y); // wrong parameter type
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(1, comp.GetDiagnostics().Count());
}
[Fact]
public void MethodGroupToDelegate05()
{
var text = @"
public class Program1
{
delegate void MyAction<T>(T x);
void Y(long x) { }
static void D(MyAction<long> o) { }
static void T()
{
D(Y); // no 'this' in scope
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(1, comp.GetDiagnostics().Count());
}
[Fact]
public void MethodGroupToDelegate06()
{
var text = @"
public class Program1
{
delegate void MyAction<T>(T x);
void Y(long x) { }
static void D(MyAction<long> o) { }
static void F()
{
D(Y); // no 'this' in scope
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(1, comp.GetDiagnostics().Count());
}
[Fact]
public void MethodGroupToDelegate07()
{
var text = @"
public class Program1
{
delegate void MyAction<T>(T x);
static void Y(long x) { }
static void D(MyAction<long> o) { }
static void F(Program1 p)
{
D(p.Y); // cannot be accessed with an instance
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(1, comp.GetDiagnostics().Count());
}
[Fact]
public void InvokeDelegate01()
{
var text = @"
public class Program
{
delegate void MyAction<T>(T x);
static void Y(long l) { }
public static void Main(string[] args)
{
MyAction<long> o = Y;
long l = 12;
o(l);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(538650, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538650")]
[Fact]
public void PropertyAmbiguity()
{
var text = @"
interface IA
{
int Goo { get; }
}
interface IB
{
int Goo { get; }
}
interface IC : IA, IB { }
class C
{
static void Main()
{
IC x = null;
int y = x.Goo;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics(
// (19,19): error CS0229: Ambiguity between 'IA.Goo' and 'IB.Goo'
// int y = x.Goo;
Diagnostic(ErrorCode.ERR_AmbigMember, "Goo").WithArguments("IA.Goo", "IB.Goo"),
// (18,12): warning CS0219: The variable 'x' is assigned but its value is never used
// IC x = null;
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x")
);
}
[WorkItem(538770, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538770")]
[Fact]
public void DelegateMethodAmbiguity()
{
var text = @"
delegate void MyAction<T>(T x);
interface I1
{
object Y { get; }
}
interface I2
{
void Y(long l);
}
interface I3 : I1, I2 { }
public class Program : I3
{
object I1.Y
{
get
{
return null;
}
}
void I2.Y(long l) { }
public static void Main(string[] args)
{
I3 p = new Program();
MyAction<long> o = p.Y;
long l = 12;
o(l);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
var diags = comp.GetDiagnostics();
Assert.Equal(0, diags.Count(d => d.Severity == DiagnosticSeverity.Error));
Assert.Equal(0, diags.Count(d => d.Severity == DiagnosticSeverity.Warning));
}
[WorkItem(538835, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538835")]
[Fact]
public void LocalReferenceTypeConsts()
{
var text = @"
public class c1
{
}
public class Program
{
static void Main()
{
const c1 C = null;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics(
// (10,18): warning CS0219: The variable 'C' is assigned but its value is never used
// const c1 C = null;
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "C").WithArguments("C")
);
}
[WorkItem(538617, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538617")]
[Fact]
public void TypeParameterNotInvocable()
{
var text = @"
class B
{
public static void T() { }
}
class A<T> : B
{
static void Goo()
{
T();
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(539591, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539591")]
[Fact]
public void ParenthesizedSetOnlyProperty()
{
var text = @"
namespace ParenthesizedExpression
{
class A
{
int p;
public int P
{
set
{
p = value;
}
}
static void Main()
{
A a = new A();
a.P = 10;
(a.P) = 11; //devdiv bug 168519.
}
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(5608, "DevDiv_Projects/Roslyn")]
[Fact]
public void TypeAliasNameIsSameAsProp()
{
var text = @"using System;
using Kind = MyKind;
enum MyKind
{
Value,
}
class C
{
public Kind Kind { get { return 0; } }
public static void Main()
{
Console.WriteLine(Kind.Value);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(539929, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539929")]
[Fact]
public void TypeWithSameNameAsProp()
{
var text = @"using System;
enum Color
{
Chartreuse,
}
class C
{
public static Color Color { get { return 0; } }
public static void Main()
{
Console.WriteLine(Color.Chartreuse);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(541504, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541504")]
[Fact]
public void TypeWithSameNameAsProp2()
{
var text = @"
enum ProtectionLevel
{
Privacy = 0
}
class F
{
ProtectionLevel p = ProtectionLevel.Privacy;
ProtectionLevel ProtectionLevel { get { return 0; } }
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics(
// (8,19): warning CS0414: The field 'F.p' is assigned but its value is never used
// ProtectionLevel p = ProtectionLevel.Privacy;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "p").WithArguments("F.p")
);
}
[WorkItem(541505, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541505")]
[Fact]
public void TypeWithSameNameAsProp3()
{
var text = @"
using System.ComponentModel;
enum ProtectionLevel
{
Privacy = 0
}
class F
{
[DefaultValue(ProtectionLevel.Privacy)]
ProtectionLevel ProtectionLevel { get { return 0; } }
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(string.Empty, string.Join(Environment.NewLine, comp.GetDiagnostics()));
}
[WorkItem(539622, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539622")]
[Fact]
public void AccessTypeThroughAliasNamespace()
{
var text = @"
namespace Conformance.Expressions
{
using LevelInner = LevelOne.LevelTwo.LevelThree;
public class LevelInner<A>
{
public class LevelThreeClass
{
public static int F1 = 1;
}
}
public class Test
{
public static int Main()
{
return LevelInner.LevelThreeClass.F1; // should not error (Roslyn CS0117)
}
}
}
namespace LevelOne.LevelTwo.LevelThree
{
public class LevelThreeClass
{
public static int F1 = 0;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(540105, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540105")]
[Fact]
public void WarningPassLocalAsRefParameter()
{
var text = @"
public class MyClass
{
public int MyMeth(ref int mbc) { return 1; }
}
public class TestClass
{
public static int Main()
{
int retval = 3;
MyClass mc = new MyClass();
int i = 1;
retval = mc.MyMeth(ref i);
return retval -1;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(540105, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540105")]
[Fact]
public void WarningPassLocalAsOutParameter()
{
var text = @"
public class MyClass
{
public int MyMeth(out int mbc) { mbc = 1; return mbc; }
}
public class TestClass
{
public static int Main()
{
MyClass mc = new MyClass();
int i;
int retval = mc.MyMeth(out i);
return retval - 1;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(540270, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540270")]
[Fact]
public void SimpleNameThroughUsingAlias()
{
var text = @"using System;
using Kind = MyKind;
enum MyKind
{
Value,
}
class C
{
public Kind Kind { get { return 0; } }
public static void Main()
{
Console.WriteLine(Kind.Value);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[WorkItem(544434, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544434")]
[Fact]
public void MethodInvocationWithMultipleArgsToParams()
{
var text = @"
using System;
class Test
{
static void Main()
{
int i = 9;
Console.Write(""[{0}, {1}, {2}] = {3,2} "", i, i, i, i);
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(1118749, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1118749")]
public void InstanceFieldOfEnclosingStruct()
{
var text = @"
struct Outer
{
private int f1;
void M() { f1 = f1 + 1; }
public struct Inner
{
public Inner(int xyzzy)
{
var x = f1 - 1;
}
}
}";
var tree = Parse(text);
var comp = CreateCompilation(tree);
Assert.Equal(0, comp.GetDeclarationDiagnostics().Count());
comp.GetMethodBodyDiagnostics().Verify(
// (10,21): error CS0120: An object reference is required for the non-static field, method, or property 'Outer.f1'
// var x = f1 - 1;
Diagnostic(ErrorCode.ERR_ObjectRequired, "f1").WithArguments("Outer.f1").WithLocation(10, 21)
);
}
[Fact, WorkItem(8556, "https://github.com/dotnet/roslyn/issues/8556")]
public void CastAmbiguousMethodGroupTypeProducesCorrectErrorMessage()
{
var text = @"
using System;
public delegate void Goo ();
class D
{
public static implicit operator D (Action d)
{
return new D ();
}
public static explicit operator D (Goo d)
{
return new D ();
}
}
class Program
{
static void Main()
{
D d = (D) Main;
}
}
";
var tree = Parse(text);
var comp = CreateCompilation(tree);
comp.GetMethodBodyDiagnostics().Verify(
// (23,15): error CS0457: Ambiguous user defined conversions 'D.explicit operator D(Goo)' and 'D.implicit operator D(Action)' when converting from 'method group' to 'D'
// D d = (D) Main;
Diagnostic(ErrorCode.ERR_AmbigUDConv, "(D) Main").WithArguments("D.explicit operator D(Goo)", "D.implicit operator D(System.Action)", "method group", "D").WithLocation(23, 15)
);
}
}
}
|