|
// 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.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 GetSemanticInfoTests : SemanticModelTestBase
{
#region helpers
internal List<string> GetLookupNames(string testSrc)
{
var parseOptions = TestOptions.Regular;
var compilation = CreateCompilationWithMscorlib461(testSrc, parseOptions: parseOptions);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var position = testSrc.Contains("/*<bind>*/") ? GetPositionForBinding(tree) : GetPositionForBinding(testSrc);
return model.LookupNames(position);
}
internal List<ISymbol> GetLookupSymbols(string testSrc, NamespaceOrTypeSymbol container = null, string name = null, int? arity = null, bool isScript = false, IEnumerable<string> globalUsings = null)
{
var tree = Parse(testSrc, options: isScript ? TestOptions.Script : TestOptions.Regular);
var compilation = CreateCompilationWithMscorlib461(new[] { tree }, options: TestOptions.ReleaseDll.WithUsings(globalUsings));
var model = compilation.GetSemanticModel(tree);
var position = testSrc.Contains("/*<bind>*/") ? GetPositionForBinding(tree) : GetPositionForBinding(testSrc);
return model.LookupSymbols(position, container.GetPublicSymbol(), name).Where(s => !arity.HasValue || arity == s.GetSymbol().GetMemberArity()).ToList();
}
#endregion helpers
#region tests
[Fact]
public void LookupExpressionBodyProp01()
{
var text = @"
class C
{
public int P => /*<bind>*/10/*</bind>*/;
}";
var actual = GetLookupNames(text).ListToSortedString();
var expected_lookupNames = new List<string>
{
"C",
"Equals",
"Finalize",
"GetHashCode",
"GetType",
"MemberwiseClone",
"Microsoft",
"P",
"ReferenceEquals",
"System",
"ToString"
};
Assert.Equal(expected_lookupNames.ListToSortedString(), actual);
}
[Fact]
public void LookupExpressionBodiedMethod01()
{
var text = @"
class C
{
public int M() => /*<bind>*/10/*</bind>*/;
}";
var actual = GetLookupNames(text).ListToSortedString();
var expected_lookupNames = new List<string>
{
"C",
"Equals",
"Finalize",
"GetHashCode",
"GetType",
"MemberwiseClone",
"Microsoft",
"M",
"ReferenceEquals",
"System",
"ToString"
};
Assert.Equal(expected_lookupNames.ListToSortedString(), actual);
}
[WorkItem(538262, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538262")]
[Fact]
public void LookupCompilationUnitSyntax()
{
var testSrc = @"
/*<bind>*/
class Test
{
}
/*</bind>*/
";
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupSymbols(testSrc);
}
[WorkItem(527476, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527476")]
[Fact]
public void LookupConstrAndDestr()
{
var testSrc = @"
class Test
{
Test()
{
}
Test(int i)
{
}
~Test()
{
}
static /*<bind>*/void/*</bind>*/Main()
{
}
}
";
List<string> expected_lookupNames = new List<string>
{
"Equals",
"Finalize",
"GetHashCode",
"GetType",
"Main",
"MemberwiseClone",
"Microsoft",
"ReferenceEquals",
"System",
"Test",
"ToString"
};
List<string> expected_lookupSymbols = new List<string>
{
"Microsoft",
"System",
"System.Boolean System.Object.Equals(System.Object obj)",
"System.Boolean System.Object.Equals(System.Object objA, System.Object objB)",
"System.Boolean System.Object.ReferenceEquals(System.Object objA, System.Object objB)",
"System.Int32 System.Object.GetHashCode()",
"System.Object System.Object.MemberwiseClone()",
"void System.Object.Finalize()",
"System.String System.Object.ToString()",
"System.Type System.Object.GetType()",
"void Test.Finalize()",
"void Test.Main()",
"Test"
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = GetLookupSymbols(testSrc);
Assert.Equal(expected_lookupNames.ListToSortedString(), actual_lookupNames.ListToSortedString());
Assert.Equal(expected_lookupSymbols.ListToSortedString(), actual_lookupSymbols.ListToSortedString());
}
[WorkItem(527477, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527477")]
[Fact]
public void LookupNotYetDeclLocalVar()
{
var testSrc = @"
class Test
{
static void Main()
{
int j = /*<bind>*/9/*</bind>*/ ;
int k = 45;
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"j",
"k"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"j",
"k"
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
}
[WorkItem(538301, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538301")]
[Fact]
public void LookupByNameIncorrectArity()
{
var testSrc = @"
class Test
{
public static void Main()
{
int i = /*<bind>*/10/*</bind>*/;
}
}
";
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupSymbols(testSrc, name: "i", arity: 1);
var actual_lookupSymbols = GetLookupSymbols(testSrc, name: "i", arity: 1);
Assert.Empty(actual_lookupSymbols);
}
[WorkItem(538310, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538310")]
[Fact]
public void LookupInProtectedNonNestedType()
{
var testSrc = @"
protected class MyClass {
/*<bind>*/public static void Main()/*</bind>*/ {}
}
";
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupSymbols(testSrc);
}
[WorkItem(538311, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538311")]
[Fact]
public void LookupClassContainsVolatileEnumField()
{
var testSrc = @"
enum E{}
class Test {
static volatile E x;
static /*<bind>*/int/*</bind>*/ Main() {
return 1;
}
}
";
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
GetLookupSymbols(testSrc);
}
[WorkItem(538312, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538312")]
[Fact]
public void LookupUsingAlias()
{
var testSrc = @"
using T2 = System.IO;
namespace T1
{
class Test
{
static /*<bind>*/void/*</bind>*/ Main()
{
}
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"T1",
"T2"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"T1",
"T2"
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
}
[WorkItem(538313, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538313")]
[Fact]
public void LookupUsingNameSpaceContSameTypeNames()
{
var testSrc = @"
namespace T1
{
using T2;
public class Test
{
static /*<bind>*/int/*</bind>*/ Main()
{
return 1;
}
}
}
namespace T2
{
public class Test
{
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"T1",
"T2",
"Test"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"T1",
"T2",
"T1.Test",
//"T2.Test" this is hidden by T1.Test
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[2], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[2], actual_lookupSymbols_as_string);
}
[WorkItem(527489, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527489")]
[Fact]
public void LookupMustNotBeNonInvocableMember()
{
var testSrc = @"
class Test
{
public void TestMeth(int i, int j)
{
int m = /*<bind>*/10/*</bind>*/;
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"TestMeth",
"i",
"j",
"m",
"System",
"Microsoft",
"Test"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"void Test.TestMeth(System.Int32 i, System.Int32 j)",
"System.Int32 i",
"System.Int32 j",
"System.Int32 m",
"System",
"Microsoft",
"Test"
};
var comp = CreateCompilation(testSrc);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var position = GetPositionForBinding(tree);
var binder = ((CSharpSemanticModel)model).GetEnclosingBinder(position);
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var info = LookupSymbolsInfo.GetInstance();
binder.AddLookupSymbolsInfo(info, LookupOptions.MustBeInvocableIfMember);
var actual_lookupNames = info.Names;
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = actual_lookupNames.SelectMany(name =>
{
var lookupResult = LookupResult.GetInstance();
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
binder.LookupSymbolsSimpleName(
lookupResult,
qualifierOpt: null,
plainName: name,
arity: 0,
basesBeingResolved: null,
options: LookupOptions.MustBeInvocableIfMember,
diagnose: false,
useSiteDiagnostics: ref useSiteDiagnostics);
Assert.Null(useSiteDiagnostics);
Assert.True(lookupResult.IsMultiViable || lookupResult.Kind == LookupResultKind.NotReferencable);
var result = lookupResult.Symbols.ToArray();
lookupResult.Free();
return result;
});
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[2], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[3], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[4], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[5], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[2], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[3], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[4], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[5], actual_lookupSymbols_as_string);
info.Free();
}
[WorkItem(538365, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538365")]
[Fact]
public void LookupWithNameZeroArity()
{
var testSrc = @"
class Test
{
private void F<T>(T i)
{
}
private void F<T, U>(T i, U j)
{
}
private void F(int i)
{
}
private void F(int i, int j)
{
}
public static /*<bind>*/void/*</bind>*/ Main()
{
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"F"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"void Test.F(System.Int32 i)",
"void Test.F(System.Int32 i, System.Int32 j)"
};
List<string> not_expected_in_lookupSymbols = new List<string>
{
"void Test.F<T>(T i)",
"void Test.F<T, U>(T i, U j)"
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = GetLookupSymbols(testSrc, name: "F", arity: 0);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Equal(2, actual_lookupSymbols.Count);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.DoesNotContain(not_expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.DoesNotContain(not_expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
}
[WorkItem(538365, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538365")]
[Fact]
public void LookupWithNameZeroArityAndLookupOptionsAllMethods()
{
var testSrc = @"
class Test
{
public void F<T>(T i)
{
}
public void F<T, U>(T i, U j)
{
}
public void F(int i)
{
}
public void F(int i, int j)
{
}
public void Main()
{
return;
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"F"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"void Test.F(System.Int32 i)",
"void Test.F(System.Int32 i, System.Int32 j)",
"void Test.F<T>(T i)",
"void Test.F<T, U>(T i, U j)"
};
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var comp = CreateCompilation(testSrc);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var position = testSrc.IndexOf("return", StringComparison.Ordinal);
var binder = ((CSharpSemanticModel)model).GetEnclosingBinder(position);
var lookupResult = LookupResult.GetInstance();
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
binder.LookupSymbolsSimpleName(lookupResult, qualifierOpt: null, plainName: "F", arity: 0, basesBeingResolved: null, options: LookupOptions.AllMethodsOnArityZero, diagnose: false, useSiteDiagnostics: ref useSiteDiagnostics);
Assert.Null(useSiteDiagnostics);
Assert.True(lookupResult.IsMultiViable);
var actual_lookupSymbols_as_string = lookupResult.Symbols.Select(e => e.ToTestDisplayString()).ToArray();
lookupResult.Free();
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = model.LookupNames(position);
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Equal(4, actual_lookupSymbols_as_string.Length);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[2], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[3], actual_lookupSymbols_as_string);
}
[WorkItem(539160, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539160")]
[Fact]
public void LookupExcludeInAppropriateNS()
{
var testSrc = @"
class Test
{
public static /*<bind>*/void/*</bind>*/ Main()
{
}
}
";
var srcTrees = new SyntaxTree[] { Parse(testSrc) };
var refs = new MetadataReference[] { SystemDataRef };
CSharpCompilation compilation = CSharpCompilation.Create("Test.dll", srcTrees, refs);
var tree = srcTrees[0];
var model = compilation.GetSemanticModel(tree);
List<string> not_expected_in_lookup = new List<string>
{
"<CrtImplementationDetails>",
"<CppImplementationDetails>"
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = model.LookupNames(GetPositionForBinding(tree), null).ToList();
var actual_lookupNames_ignoreAcc = model.LookupNames(GetPositionForBinding(tree), null).ToList();
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = model.LookupSymbols(GetPositionForBinding(tree));
var actual_lookupSymbols_ignoreAcc = model.LookupSymbols(GetPositionForBinding(tree));
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
var actual_lookupSymbols_ignoreAcc_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.DoesNotContain(not_expected_in_lookup[0], actual_lookupNames);
Assert.DoesNotContain(not_expected_in_lookup[1], actual_lookupNames);
Assert.DoesNotContain(not_expected_in_lookup[0], actual_lookupNames_ignoreAcc);
Assert.DoesNotContain(not_expected_in_lookup[1], actual_lookupNames_ignoreAcc);
Assert.DoesNotContain(not_expected_in_lookup[0], actual_lookupSymbols_as_string);
Assert.DoesNotContain(not_expected_in_lookup[1], actual_lookupSymbols_as_string);
Assert.DoesNotContain(not_expected_in_lookup[0], actual_lookupSymbols_ignoreAcc_as_string);
Assert.DoesNotContain(not_expected_in_lookup[1], actual_lookupSymbols_ignoreAcc_as_string);
}
/// <summary>
/// Verify that there's a way to look up only the members of the base type that are visible
/// from the current type.
/// </summary>
[Fact]
[WorkItem(539814, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539814")]
public void LookupProtectedInBase()
{
var testSrc = @"
class A
{
private void Hidden() { }
protected void Goo() { }
}
class B : A
{
void Bar()
{
/*<bind>*/base/*</bind>*/.Goo();
}
}
";
var srcTrees = new SyntaxTree[] { Parse(testSrc) };
var refs = new MetadataReference[] { SystemDataRef };
CSharpCompilation compilation = CSharpCompilation.Create("Test.dll", srcTrees, refs);
var tree = srcTrees[0];
var model = compilation.GetSemanticModel(tree);
var baseExprNode = GetSyntaxNodeForBinding(GetSyntaxNodeList(tree));
Assert.Equal("base", baseExprNode.ToString());
var baseExprLocation = baseExprNode.SpanStart;
Assert.NotEqual(0, baseExprLocation);
var baseExprInfo = model.GetTypeInfo((ExpressionSyntax)baseExprNode);
Assert.NotEqual(default, baseExprInfo);
var baseExprType = (INamedTypeSymbol)baseExprInfo.Type;
Assert.NotNull(baseExprType);
Assert.Equal("A", baseExprType.Name);
var symbols = model.LookupBaseMembers(baseExprLocation);
Assert.Equal("void A.Goo()", symbols.Single().ToTestDisplayString());
var names = model.LookupNames(baseExprLocation, useBaseReferenceAccessibility: true);
Assert.Equal("Goo", names.Single());
}
[WorkItem(528263, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528263")]
[Fact]
public void LookupStartOfScopeMethodBody()
{
var testSrc = @"public class start
{
static public void Main()
/*pos*/{
int num=10;
}
";
List<string> expected_in_lookupNames = new List<string>
{
"Main",
"start",
"num"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"void start.Main()",
"start",
"System.Int32 num"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Equal('{', testSrc[GetPositionForBinding(testSrc)]);
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[2], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[2], actual_lookupSymbols_as_string);
}
[WorkItem(528263, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528263")]
[Fact]
public void LookupEndOfScopeMethodBody()
{
var testSrc = @"public class start
{
static public void Main()
{
int num=10;
/*pos*/}
";
List<string> expected_in_lookupNames = new List<string>
{
"Main",
"start"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"void start.Main()",
"start"
};
List<string> not_expected_in_lookupNames = new List<string>
{
"num"
};
List<string> not_expected_in_lookupSymbols = new List<string>
{
"System.Int32 num"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Equal('}', testSrc[GetPositionForBinding(testSrc)]);
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.DoesNotContain(not_expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.DoesNotContain(not_expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(540888, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540888")]
[Fact]
public void LookupLambdaParamInConstructorInitializer()
{
var testSrc = @"
using System;
class MyClass
{
public MyClass(Func<int, int> x)
{
}
public MyClass(int j, int k)
: this(lambdaParam => /*pos*/lambdaParam)
{
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"j",
"k",
"lambdaParam"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"System.Int32 j",
"System.Int32 k",
"System.Int32 lambdaParam"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[2], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[2], actual_lookupSymbols_as_string);
}
[WorkItem(540893, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540893")]
[Fact]
public void TestForLocalVarDeclLookupAtForKeywordInForStmt()
{
var testSrc = @"
class MyClass
{
static void Main()
{
/*pos*/for (int forVar = 10; forVar < 10; forVar++)
{
}
}
}
";
List<string> not_expected_in_lookupNames = new List<string>
{
"forVar"
};
List<string> not_expected_in_lookupSymbols = new List<string>
{
"System.Int32 forVar",
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.DoesNotContain(not_expected_in_lookupNames[0], actual_lookupNames);
Assert.DoesNotContain(not_expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(540894, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540894")]
[Fact]
public void TestForeachIterVarLookupAtForeachKeyword()
{
var testSrc = @"
class MyClass
{
static void Main()
{
System.Collections.Generic.List<int> listOfNumbers = new System.Collections.Generic.List<int>();
/*pos*/foreach (int number in listOfNumbers)
{
}
}
}
";
List<string> not_expected_in_lookupNames = new List<string>
{
"number"
};
List<string> not_expected_in_lookupSymbols = new List<string>
{
"System.Int32 number",
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.DoesNotContain(not_expected_in_lookupNames[0], actual_lookupNames);
Assert.DoesNotContain(not_expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(540912, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540912")]
[Fact]
public void TestLookupInConstrInitIncompleteConstrDecl()
{
var testSrc = @"
class MyClass
{
public MyClass(int x)
{
}
public MyClass(int j, int k) :this(/*pos*/k)
";
List<string> expected_in_lookupNames = new List<string>
{
"j",
"k"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"System.Int32 j",
"System.Int32 k",
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupNames[1], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
Assert.Contains(expected_in_lookupSymbols[1], actual_lookupSymbols_as_string);
}
[WorkItem(541060, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541060")]
[Fact]
public void TestLookupInsideIncompleteNestedLambdaBody()
{
var testSrc = @"
class C
{
C()
{
D(() =>
{
D(() =>
{
}/*pos*/
";
List<string> expected_in_lookupNames = new List<string>
{
"C"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"C"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.NotEmpty(actual_lookupNames);
Assert.NotEmpty(actual_lookupSymbols);
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(541611, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541611")]
[Fact]
public void LookupLambdaInsideAttributeUsage()
{
var testSrc = @"
using System;
class Program
{
[ObsoleteAttribute(x=>x/*pos*/
static void Main(string[] args)
{
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"x"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"? x"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[Fact]
public void LookupInsideLocalFunctionAttribute()
{
var testSrc = @"
using System;
class Program
{
const int w = 0451;
void M()
{
int x = 42;
const int y = 123;
[ObsoleteAttribute(/*pos*/
static void local1(int z)
{
}
}
}
";
var lookupNames = GetLookupNames(testSrc);
var lookupSymbols = GetLookupSymbols(testSrc).Select(e => e.ToTestDisplayString()).ToList();
Assert.Contains("w", lookupNames);
Assert.Contains("y", lookupNames);
Assert.Contains("System.Int32 Program.w", lookupSymbols);
Assert.Contains("System.Int32 y", lookupSymbols);
}
[Fact]
public void LookupInsideLambdaAttribute()
{
var testSrc = @"
using System;
class Program
{
const int w = 0451;
void M()
{
int x = 42;
const int y = 123;
Action<int> a =
[ObsoleteAttribute(/*pos*/
(int z) => { };
}
}
";
var lookupNames = GetLookupNames(testSrc);
var lookupSymbols = GetLookupSymbols(testSrc).Select(e => e.ToTestDisplayString()).ToList();
Assert.Contains("w", lookupNames);
Assert.Contains("y", lookupNames);
Assert.Contains("System.Int32 Program.w", lookupSymbols);
Assert.Contains("System.Int32 y", lookupSymbols);
}
[Fact]
public void LookupInsideIncompleteStatementAttribute()
{
var testSrc = @"
using System;
class Program
{
const int w = 0451;
void M()
{
int x = 42;
const int y = 123;
[ObsoleteAttribute(/*pos*/
int
}
}
";
var lookupNames = GetLookupNames(testSrc);
var lookupSymbols = GetLookupSymbols(testSrc).Select(e => e.ToTestDisplayString()).ToList();
Assert.Contains("w", lookupNames);
Assert.Contains("y", lookupNames);
Assert.Contains("System.Int32 Program.w", lookupSymbols);
Assert.Contains("System.Int32 y", lookupSymbols);
}
[WorkItem(541909, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541909")]
[Fact]
public void LookupFromRangeVariableAfterFromClause()
{
var testSrc = @"
class Program
{
static void Main(string[] args)
{
var q = from i in new int[] { 4, 5 } where /*pos*/
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"i"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"? i"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(541921, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541921")]
[Fact]
public void LookupFromRangeVariableInsideNestedFromClause()
{
var testSrc = @"
class Program
{
static void Main(string[] args)
{
string[] strings = { };
var query = from s in strings
from s1 in /*pos*/
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"s"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"? s"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(541919, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541919")]
[Fact]
public void LookupLambdaVariableInQueryExpr()
{
var testSrc = @"
class Program
{
static void Main(string[] args)
{
Func<int, IEnumerable<int>> f1 = (x) => from n in /*pos*/
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"x"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"x"
};
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.Name);
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[WorkItem(541910, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541910")]
[Fact]
public void LookupInsideQueryExprOutsideTypeDecl()
{
var testSrc = @"var q = from i in/*pos*/ f";
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.NotEmpty(actual_lookupNames);
Assert.NotEmpty(actual_lookupSymbols_as_string);
}
[WorkItem(542203, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542203")]
[Fact]
public void LookupInsideQueryExprInMalformedFromClause()
{
var testSrc = @"
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
int[] numbers = new int[] { 4, 5 };
var q1 = from I<x/*pos*/ in numbers.Where(x1 => x1 > 2) select x;
}
}
";
// Get the list of LookupNames at the location at the end of the /*pos*/ tag
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location at the end of the /*pos*/ tag
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToTestDisplayString());
Assert.NotEmpty(actual_lookupNames);
Assert.NotEmpty(actual_lookupSymbols_as_string);
}
[WorkItem(543295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543295")]
[Fact]
public void MultipleOverlappingInterfaceConstraints()
{
var testSrc =
@"public interface IEntity
{
object Key { get; }
}
public interface INumberedProjectChild
: IEntity
{ }
public interface IAggregateRoot : IEntity
{
}
public interface ISpecification<TCandidate>
{
void IsSatisfiedBy(TCandidate candidate);
}
public abstract class Specification<TCandidate> : ISpecification<TCandidate>
{
public abstract void IsSatisfiedBy(TCandidate candidate);
}
public class NumberSpecification<TCandidate>
: Specification<TCandidate> where TCandidate : IAggregateRoot,
INumberedProjectChild
{
public override void IsSatisfiedBy(TCandidate candidate)
{
var key = candidate.Key;
}
}";
CreateCompilation(testSrc).VerifyDiagnostics();
}
[WorkItem(529406, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529406")]
[Fact]
public void FixedPointerInitializer()
{
var testSrc = @"
class Program
{
static int num = 0;
unsafe static void Main(string[] args)
{
fixed(int* p1 = /*pos*/&num, p2 = &num)
{
}
}
}
";
List<string> expected_in_lookupNames = new List<string>
{
"p2"
};
List<string> expected_in_lookupSymbols = new List<string>
{
"p2"
};
// Get the list of LookupNames at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupNames = GetLookupNames(testSrc);
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode enclosed within the <bind> </bind> tags
var actual_lookupSymbols = GetLookupSymbols(testSrc);
var actual_lookupSymbols_as_string = actual_lookupSymbols.Select(e => e.ToString()).ToList();
Assert.Contains(expected_in_lookupNames[0], actual_lookupNames);
Assert.Contains(expected_in_lookupSymbols[0], actual_lookupSymbols_as_string);
}
[Fact]
public void LookupSymbolsAtEOF()
{
var source =
@"class
{
}";
var tree = Parse(source);
var comp = CreateCompilationWithMscorlib40(new[] { tree });
var model = comp.GetSemanticModel(tree);
var eof = tree.GetCompilationUnitRoot().FullSpan.End;
Assert.NotEqual(0, eof);
var symbols = model.LookupSymbols(eof);
CompilationUtils.CheckISymbols(symbols, "System", "Microsoft");
}
[Fact, WorkItem(546523, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546523")]
public void TestLookupSymbolsNestedNamespacesNotImportedByUsings_01()
{
var source =
@"
using System;
class Program
{
static void Main(string[] args)
{
/*pos*/
}
}
";
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode
var actual_lookupSymbols = GetLookupSymbols(source);
// Verify nested namespaces *are not* imported.
var systemNS = (INamespaceSymbol)actual_lookupSymbols.Where((sym) => sym.Name.Equals("System") && sym.Kind == SymbolKind.Namespace).Single();
INamespaceSymbol systemXmlNS = systemNS.GetNestedNamespace("Xml");
Assert.DoesNotContain(systemXmlNS, actual_lookupSymbols);
}
[Fact, WorkItem(546523, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546523")]
public void TestLookupSymbolsNestedNamespacesNotImportedByUsings_02()
{
var usings = "using X;";
var source =
@"
using aliasY = X.Y;
namespace X
{
namespace Y
{
public class InnerZ
{
}
}
public class Z
{
}
public static class StaticZ
{
}
}
public class A
{
public class B
{
}
}
class Program
{
public static void Main()
{
/*pos*/
}
}
";
// Get the list of LookupSymbols at the location of the CSharpSyntaxNode
var actual_lookupSymbols = GetLookupSymbols(usings + source, isScript: false);
TestLookupSymbolsNestedNamespaces(actual_lookupSymbols);
actual_lookupSymbols = GetLookupSymbols(source, isScript: true, globalUsings: new[] { usings });
TestLookupSymbolsNestedNamespaces(actual_lookupSymbols);
Action<ModuleSymbol> validator = (module) =>
{
NamespaceSymbol globalNS = module.GlobalNamespace;
Assert.Equal(1, globalNS.GetMembers("X").Length);
Assert.Equal(1, globalNS.GetMembers("A").Length);
Assert.Equal(1, globalNS.GetMembers("Program").Length);
Assert.Empty(globalNS.GetMembers("Y"));
Assert.Empty(globalNS.GetMembers("Z"));
Assert.Empty(globalNS.GetMembers("StaticZ"));
Assert.Empty(globalNS.GetMembers("B"));
};
CompileAndVerify(source, sourceSymbolValidator: validator, symbolValidator: validator);
}
[Fact]
[WorkItem(530826, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530826")]
public void TestAmbiguousInterfaceLookup()
{
var source =
@"delegate void D();
interface I1
{
void M();
}
interface I2
{
event D M;
}
interface I3 : I1, I2 { }
public class P : I3
{
event D I2.M { add { } remove { } }
void I1.M() { }
}
class Q : P
{
static int Main(string[] args)
{
Q p = new Q();
I3 m = p;
if (m.M is object) {}
return 0;
}
}";
var compilation = CreateCompilation(source);
var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<ExpressionSyntax>().Where(n => n.ToString() == "m.M").Single();
var symbolInfo = model.GetSymbolInfo(node);
Assert.Equal("void I1.M()", symbolInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
var node2 = (ExpressionSyntax)SyntaxFactory.SyntaxTree(node).GetRoot();
symbolInfo = model.GetSpeculativeSymbolInfo(node.Position, node2, SpeculativeBindingOption.BindAsExpression);
Assert.Equal("void I1.M()", symbolInfo.CandidateSymbols.Single().ToTestDisplayString());
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
}
[Fact]
public void TestLookupVerbatimVar()
{
var source = "class C { public static void Main() { @var v = 1; } }";
CreateCompilation(source).VerifyDiagnostics(
// (1,39): error CS0246: The type or namespace name 'var' could not be found (are you missing a using directive or an assembly reference?)
// class C { public static void Main() { @var v = 1; } }
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "@var").WithArguments("var").WithLocation(1, 39)
);
}
private void TestLookupSymbolsNestedNamespaces(List<ISymbol> actual_lookupSymbols)
{
var namespaceX = (INamespaceSymbol)actual_lookupSymbols.Where((sym) => sym.Name.Equals("X") && sym.Kind == SymbolKind.Namespace).Single();
// Verify nested namespaces within namespace X *are not* present in lookup symbols.
INamespaceSymbol namespaceY = namespaceX.GetNestedNamespace("Y");
Assert.DoesNotContain(namespaceY, actual_lookupSymbols);
INamedTypeSymbol typeInnerZ = namespaceY.GetTypeMembers("InnerZ").Single();
Assert.DoesNotContain(typeInnerZ, actual_lookupSymbols);
// Verify nested types *are not* present in lookup symbols.
var typeA = (INamedTypeSymbol)actual_lookupSymbols.Where((sym) => sym.Name.Equals("A") && sym.Kind == SymbolKind.NamedType).Single();
INamedTypeSymbol typeB = typeA.GetTypeMembers("B").Single();
Assert.DoesNotContain(typeB, actual_lookupSymbols);
// Verify aliases to nested namespaces within namespace X *are* present in lookup symbols.
var aliasY = (IAliasSymbol)actual_lookupSymbols.Where((sym) => sym.Name.Equals("aliasY") && sym.Kind == SymbolKind.Alias).Single();
Assert.Contains(aliasY, actual_lookupSymbols);
}
[Fact]
public void ExtensionMethodCall()
{
var source =
@"static class E
{
internal static void F(this object o)
{
}
}
class C
{
void M()
{
/*<bind>*/this.F/*</bind>*/();
}
}";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);
compilation.VerifyDiagnostics();
var exprs = GetExprSyntaxList(tree);
var expr = GetExprSyntaxForBinding(exprs);
var method = (IMethodSymbol)model.GetSymbolInfo(expr).Symbol;
Assert.Equal("object.F()", method.ToDisplayString());
var reducedFrom = method.ReducedFrom;
Assert.NotNull(reducedFrom);
Assert.Equal("E.F(object)", reducedFrom.ToDisplayString());
}
[WorkItem(3651, "https://github.com/dotnet/roslyn/issues/3651")]
[Fact]
public void ExtensionMethodDelegateCreation()
{
var source =
@"static class E
{
internal static void F(this object o)
{
}
}
class C
{
void M()
{
(new System.Action<object>(/*<bind>*/E.F/*</bind>*/))(this);
(new System.Action(/*<bind1>*/this.F/*</bind1>*/))();
}
}";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);
compilation.VerifyDiagnostics();
var exprs = GetExprSyntaxList(tree);
var expr = GetExprSyntaxForBinding(exprs, index: 0);
var method = (IMethodSymbol)model.GetSymbolInfo(expr).Symbol;
Assert.Null(method.ReducedFrom);
Assert.Equal("E.F(object)", method.ToDisplayString());
expr = GetExprSyntaxForBinding(exprs, index: 1);
method = (IMethodSymbol)model.GetSymbolInfo(expr).Symbol;
Assert.Equal("object.F()", method.ToDisplayString());
var reducedFrom = method.ReducedFrom;
Assert.NotNull(reducedFrom);
Assert.Equal("E.F(object)", reducedFrom.ToDisplayString());
}
[WorkItem(7493, "https://github.com/dotnet/roslyn/issues/7493")]
[Fact]
public void GenericNameLookup()
{
var source = @"using A = List<int>;";
var compilation = CreateCompilation(source).VerifyDiagnostics(
// (1,11): error CS0246: The type or namespace name 'List<>' could not be found (are you missing a using directive or an assembly reference?)
// using A = List<int>;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "List<int>").WithArguments("List<>").WithLocation(1, 11),
// (1,1): hidden CS8019: Unnecessary using directive.
// using A = List<int>;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A = List<int>;").WithLocation(1, 1));
}
#endregion tests
#region regressions
[Fact]
[WorkItem(552472, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/552472")]
public void BrokenCode01()
{
var source =
@"Dele<Str> d3 = delegate (Dele<Str> d2 = delegate ()
{
returne<double> d1 = delegate () { return 1; };
{
int result = 0;
Dels Test : Base";
var compilation = CreateCompilation(source);
var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);
SemanticModel imodel = model;
var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "returne<double>").First();
imodel.GetSymbolInfo(node, default(CancellationToken));
}
[Fact]
[WorkItem(552472, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/552472")]
public void BrokenCode02()
{
var source =
@"public delegate D D(D d);
class Program
{
public D d3 = delegate(D d2 = delegate
{
System.Object x = 3;
return null;
}) {};
public static void Main(string[] args)
{
}
}
";
var compilation = CreateCompilation(source);
var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);
SemanticModel imodel = model;
var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "System.Object").First();
imodel.GetSymbolInfo(node, default(CancellationToken));
}
[Fact]
public void InterfaceDiamondHiding()
{
var source = @"
interface T
{
int P { get; set; }
int Q { get; set; }
}
interface L : T
{
new int P { get; set; }
}
interface R : T
{
new int Q { get; set; }
}
interface B : L, R
{
}
class Test
{
int M(B b)
{
return b.P + b.Q;
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var global = comp.GlobalNamespace;
var interfaceT = global.GetMember<NamedTypeSymbol>("T");
var interfaceL = global.GetMember<NamedTypeSymbol>("L");
var interfaceR = global.GetMember<NamedTypeSymbol>("R");
var interfaceB = global.GetMember<NamedTypeSymbol>("B");
var propertyTP = interfaceT.GetMember<PropertySymbol>("P");
var propertyTQ = interfaceT.GetMember<PropertySymbol>("Q");
var propertyLP = interfaceL.GetMember<PropertySymbol>("P");
var propertyRQ = interfaceR.GetMember<PropertySymbol>("Q");
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntaxes = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().ToArray();
Assert.Equal(2, syntaxes.Length);
// The properties in T are hidden - we bind to the properties on more-derived interfaces
Assert.Equal(propertyLP.GetPublicSymbol(), model.GetSymbolInfo(syntaxes[0]).Symbol);
Assert.Equal(propertyRQ.GetPublicSymbol(), model.GetSymbolInfo(syntaxes[1]).Symbol);
int position = source.IndexOf("return", StringComparison.Ordinal);
// We do the right thing with diamond inheritance (i.e. member is hidden along all paths
// if it is hidden along any path) because we visit base interfaces in topological order.
Assert.Equal(propertyLP.GetPublicSymbol(), model.LookupSymbols(position, interfaceB.GetPublicSymbol(), "P").Single());
Assert.Equal(propertyRQ.GetPublicSymbol(), model.LookupSymbols(position, interfaceB.GetPublicSymbol(), "Q").Single());
}
[Fact]
public void SemanticModel_OnlyInvalid()
{
var source = @"
public class C
{
void M()
{
return;
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
int position = source.IndexOf("return", StringComparison.Ordinal);
var symbols = model.LookupNamespacesAndTypes(position, name: "M");
Assert.Equal(0, symbols.Length);
}
[Fact]
public void SemanticModel_InvalidHidingValid()
{
var source = @"
public class C<T>
{
public class Inner
{
void T()
{
return;
}
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var classC = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
var methodT = classC.GetMember<NamedTypeSymbol>("Inner").GetMember<MethodSymbol>("T");
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
int position = source.IndexOf("return", StringComparison.Ordinal);
var symbols = model.LookupSymbols(position, name: "T");
Assert.Equal(methodT.GetPublicSymbol(), symbols.Single()); // Hides type parameter.
symbols = model.LookupNamespacesAndTypes(position, name: "T");
Assert.Equal(classC.TypeParameters.Single().GetPublicSymbol(), symbols.Single()); // Ignore intervening method.
}
[Fact]
public void SemanticModel_MultipleValid()
{
var source = @"
public class Outer
{
void M(int x)
{
}
void M()
{
return;
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
int position = source.IndexOf("return", StringComparison.Ordinal);
var symbols = model.LookupSymbols(position, name: "M");
Assert.Equal(2, symbols.Length);
}
[Fact, WorkItem(1078958, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078958")]
public void Bug1078958()
{
const string source = @"
class C
{
static void Goo<T>()
{
/*<bind>*/T/*</bind>*/();
}
static void T() { }
}";
var symbols = GetLookupSymbols(source);
Assert.True(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1078961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078961")]
public void Bug1078961()
{
const string source = @"
class C
{
const int T = 42;
static void Goo<T>(int x = /*<bind>*/T/*</bind>*/)
{
System.Console.Write(x);
}
static void Main()
{
Goo<object>();
}
}";
var symbols = GetLookupSymbols(source);
Assert.False(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1078961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078961")]
public void Bug1078961_2()
{
const string source = @"
class A : System.Attribute
{
public A(int i) { }
}
class C
{
const int T = 42;
static void Goo<T>([A(/*<bind>*/T/*</bind>*/)] int x)
{
}
}";
var symbols = GetLookupSymbols(source);
Assert.False(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1078961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078961")]
public void Bug1078961_3()
{
const string source = @"
class A : System.Attribute
{
public A(int i) { }
}
class C
{
const int T = 42;
[A(/*<bind>*/T/*</bind>*/)]
static void Goo<T>(int x)
{
}
}";
var symbols = GetLookupSymbols(source);
Assert.False(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1078961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078961")]
public void Bug1078961_4()
{
const string source = @"
class A : System.Attribute
{
public A(int i) { }
}
class C
{
const int T = 42;
static void Goo<[A(/*<bind>*/T/*</bind>*/)] T>(int x)
{
}
}";
var symbols = GetLookupSymbols(source);
Assert.False(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1078961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078961")]
public void Bug1078961_5()
{
const string source = @"
class C
{
class T { }
static void Goo<T>(T x = default(/*<bind>*/T/*</bind>*/))
{
System.Console.Write((object)x == null);
}
static void Main()
{
Goo<object>();
}
}";
var symbols = GetLookupSymbols(source);
Assert.True(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1078961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1078961")]
public void Bug1078961_6()
{
const string source = @"
class C
{
class T { }
static void Goo<T>(T x = default(/*<bind>*/T/*</bind>*/))
{
System.Console.Write((object)x == null);
}
static void Main()
{
Goo<object>();
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var position = GetPositionForBinding(tree);
var symbols = model.LookupNamespacesAndTypes(position);
Assert.True(symbols.Any(s => s.Kind == SymbolKind.TypeParameter));
}
[Fact, WorkItem(1091936, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1091936")]
public void Bug1091936_1()
{
const string source = @"
class Program
{
static object M(long l) { return null; }
static object M(int i) { return null; }
static void Main(string[] args)
{
(M(0))?.ToString();
}
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics();
var ms = comp.GlobalNamespace.GetTypeMembers("Program").Single().GetMembers("M").OfType<MethodSymbol>();
var m = ms.Where(mm => mm.Parameters[0].Type.SpecialType == SpecialType.System_Int32).Single();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var call = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().First();
var symbolInfo = model.GetSymbolInfo(call.Expression);
Assert.NotEqual(default, symbolInfo);
Assert.Equal(symbolInfo.Symbol.GetSymbol(), m);
}
[Fact, WorkItem(1091936, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1091936")]
public void Bug1091936_2()
{
const string source = @"
class Program
{
static object M = null;
static void Main(string[] args)
{
M?.ToString();
}
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics();
var m = comp.GlobalNamespace.GetTypeMembers("Program").Single().GetMembers("M").Single();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<ConditionalAccessExpressionSyntax>().Single().Expression;
var symbolInfo = model.GetSymbolInfo(node);
Assert.NotEqual(default, symbolInfo);
Assert.Equal(symbolInfo.Symbol.GetSymbol(), m);
}
[Fact, WorkItem(1091936, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1091936")]
public void Bug1091936_3()
{
const string source = @"
class Program
{
object M = null;
static void Main(string[] args)
{
(new Program()).M?.ToString();
}
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics();
var m = comp.GlobalNamespace.GetTypeMembers("Program").Single().GetMembers("M").Single();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<ConditionalAccessExpressionSyntax>().Single().Expression;
var symbolInfo = model.GetSymbolInfo(node);
Assert.NotEqual(default, symbolInfo);
Assert.Equal(symbolInfo.Symbol.GetSymbol(), m);
}
[Fact, WorkItem(1091936, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1091936")]
public void Bug1091936_4()
{
const string source = @"
class Program
{
static void Main(string[] args)
{
var y = (System.Linq.Enumerable.Select<string, int>(args, s => int.Parse(s)))?.ToString();
}
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<GenericNameSyntax>().Single();
var symbolInfo = model.GetSymbolInfo(node);
Assert.NotEqual(default, symbolInfo);
Assert.NotNull(symbolInfo.Symbol);
}
[Fact]
public void GenericAttribute_LookupSymbols_01()
{
var source = @"
using System;
class Attr1<T> : Attribute { public Attr1(T t) { } }
[Attr1<string>(""a"")]
class C { }";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var node = tree.GetRoot().DescendantNodes().OfType<AttributeSyntax>().Single();
var symbol = model.GetSymbolInfo(node);
Assert.Equal("Attr1<System.String>..ctor(System.String t)", symbol.Symbol.ToTestDisplayString());
}
[Fact]
public void GenericAttribute_LookupSymbols_02()
{
var source = @"
using System;
class Attr1<T> : Attribute { public Attr1(T t) { } }
[Attr1</*<bind>*/string/*</bind>*/>]
class C { }";
var names = GetLookupNames(source);
Assert.Contains("C", names);
Assert.Contains("Attr1", names);
}
#endregion
}
}
|