|
// 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.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Basic.Reference.Assemblies;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.SymbolId;
public partial class SymbolKeyTest : SymbolKeyTestBase
{
#region "Metadata vs. Source"
[Fact]
public void M2SNamedTypeSymbols01()
{
var src1 = """
using System;
public delegate void D(int p1, string p2);
namespace N1.N2
{
public interface I { }
namespace N3
{
public class C
{
public struct S
{
public enum E { Zero, One, Two }
public void M(int n) { Console.WriteLine(n); }
}
}
}
}
""";
var src2 = """
using System;
using N1.N2.N3;
public class App : C
{
private event D myEvent;
internal N1.N2.I Prop { get; set; }
protected C.S.E this[int x] { set { } }
public void M(C.S s) { s.M(123); }
}
""";
var comp1 = CreateCompilation(src1);
// Compilation to Compilation
var comp2 = (Compilation)CreateCompilation(src2, [new CSharpCompilationReference(comp1)]);
var originalSymbols = GetSourceSymbols(comp1, SymbolCategory.DeclaredType).OrderBy(s => s.Name).ToList();
Assert.Equal(5, originalSymbols.Count);
// ---------------------------
// Metadata symbols
var typesym = comp2.SourceModule.GlobalNamespace.GetTypeMembers("App").FirstOrDefault();
// 'D'
var member01 = (typesym.GetMembers("myEvent").Single() as IEventSymbol).Type;
// 'I'
var member02 = (typesym.GetMembers("Prop").Single() as IPropertySymbol).Type;
// 'C'
var member03 = typesym.BaseType;
// 'S'
var member04 = (typesym.GetMembers("M").Single() as IMethodSymbol).Parameters[0].Type;
// 'E'
var member05 = (typesym.GetMembers(WellKnownMemberNames.Indexer).Single() as IPropertySymbol).Type;
ResolveAndVerifySymbol(member03, originalSymbols[0], comp1, SymbolKeyComparison.None);
ResolveAndVerifySymbol(member01, originalSymbols[1], comp1, SymbolKeyComparison.None);
ResolveAndVerifySymbol(member05, originalSymbols[2], comp1, SymbolKeyComparison.None);
ResolveAndVerifySymbol(member02, originalSymbols[3], comp1, SymbolKeyComparison.None);
ResolveAndVerifySymbol(member04, originalSymbols[4], comp1, SymbolKeyComparison.None);
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542700")]
public void M2SNonTypeMemberSymbols01()
{
var src1 = """
using System;
namespace N1
{
public interface IGoo
{
void M(int p1, int p2);
void M(params short[] ary);
void M(string p1);
void M(ref string p1);
}
public struct S
{
public event Action<S> PublicEvent { add { } remove { } }
public IGoo PublicField;
public string PublicProp { get; set; }
public short this[sbyte p] { get { return p; } }
}
}
""";
var src2 = """
using System;
using AN = N1;
public class App
{
static void Main()
{
var obj = new AN.S();
/*<bind0>*/obj.PublicEvent/*</bind0>*/ += EH;
var igoo = /*<bind1>*/obj.PublicField/*</bind1>*/;
/*<bind3>*/igoo.M(/*<bind2>*/obj.PublicProp/*</bind2>*/)/*</bind3>*/;
/*<bind5>*/igoo.M(obj[12], /*<bind4>*/obj[123]/*</bind4>*/)/*</bind5>*/;
}
static void EH(AN.S s) { }
}
""";
var comp1 = CreateCompilation(src1);
// Compilation to Assembly
var comp2 = CreateCompilation(src2, [comp1.EmitToImageReference()]);
// ---------------------------
// Source symbols
var originalSymbols = GetSourceSymbols(comp1, SymbolCategory.NonTypeMember | SymbolCategory.Parameter).ToList();
originalSymbols = originalSymbols.Where(s => !s.IsAccessor() && s.Kind != SymbolKind.Parameter).OrderBy(s => s.Name).Select(s => s).ToList();
Assert.Equal(8, originalSymbols.Count);
// ---------------------------
// Metadata symbols
var bindingtuples = GetBindingNodesAndModel<ExpressionSyntax>(comp2);
var model = bindingtuples.Item2;
var list = bindingtuples.Item1;
Assert.Equal(6, list.Count);
// event
ResolveAndVerifySymbol(list[0], originalSymbols[4], model, comp1, SymbolKeyComparison.None);
// field
ResolveAndVerifySymbol(list[1], originalSymbols[5], model, comp1, SymbolKeyComparison.None);
// prop
ResolveAndVerifySymbol(list[2], originalSymbols[6], model, comp1, SymbolKeyComparison.None);
// index:
ResolveAndVerifySymbol(list[4], originalSymbols[7], model, comp1, SymbolKeyComparison.None);
// M(string p1)
ResolveAndVerifySymbol(list[3], originalSymbols[2], model, comp1, SymbolKeyComparison.None);
// M(params short[] ary)
ResolveAndVerifySymbol(list[5], originalSymbols[1], model, comp1, SymbolKeyComparison.None);
}
#endregion
#region "Metadata vs. Metadata"
[Fact]
public void M2MMultiTargetingMsCorLib01()
{
var src1 = """
using System;
using System.IO;
public class A
{
public FileInfo GetFileInfo(string path)
{
if (File.Exists(path))
{
return new FileInfo(path);
}
return null;
}
public void PrintInfo(Array ary, ref DateTime time)
{
if (ary != null)
Console.WriteLine(ary);
else
Console.WriteLine("null");
time = DateTime.Now;
}
}
""";
var src2 = """
using System;
class Test
{
static void Main()
{
var a = new A();
var fi = a.GetFileInfo(null);
Console.WriteLine(fi);
var dt = DateTime.Now;
var ary = Array.CreateInstance(typeof(string), 2);
a.PrintInfo(ary, ref dt);
}
}
""";
var comp20 = (Compilation)CreateEmptyCompilation(src1, [Net40.References.mscorlib]);
// "Compilation 2 Assembly"
var comp40 = (Compilation)CreateCompilation(src2, [comp20.EmitToImageReference()]);
var typeA = comp20.SourceModule.GlobalNamespace.GetTypeMembers("A").Single();
var mem20_1 = typeA.GetMembers("GetFileInfo").Single() as IMethodSymbol;
var mem20_2 = typeA.GetMembers("PrintInfo").Single() as IMethodSymbol;
// FileInfo
var mtsym20_1 = mem20_1.ReturnType;
Assert.Equal(2, mem20_2.Parameters.Length);
// Array
var mtsym20_2 = mem20_2.Parameters[0].Type;
// ref DateTime
var mtsym20_3 = mem20_2.Parameters[1].Type;
// ====================
var typeTest = comp40.SourceModule.GlobalNamespace.GetTypeMembers("Test").FirstOrDefault();
var mem40 = typeTest.GetMembers("Main").Single() as IMethodSymbol;
var list = GetBlockSyntaxList(mem40);
var model = comp40.GetSemanticModel(comp40.SyntaxTrees.First());
foreach (var body in list)
{
var df = model.AnalyzeDataFlow(body.Statements.First(), body.Statements.Last());
foreach (var local in df.VariablesDeclared)
{
var localType = ((ILocalSymbol)local).Type;
if (local.Name == "fi")
{
ResolveAndVerifySymbol(localType, mtsym20_1, comp20, SymbolKeyComparison.None);
}
else if (local.Name == "ary")
{
ResolveAndVerifySymbol(localType, mtsym20_2, comp20, SymbolKeyComparison.None);
}
else if (local.Name == "dt")
{
ResolveAndVerifySymbol(localType, mtsym20_3, comp20, SymbolKeyComparison.None);
}
}
}
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546255")]
public void M2MMultiTargetingMsCorLib02()
{
var src1 = """
using System;
namespace Mscorlib20
{
public interface IGoo
{
// interface
IDisposable Prop { get; set; }
// class
Exception this[ArgumentException t] { get; }
}
public class CGoo : IGoo
{
// enum
public DayOfWeek PublicField;
// delegate
public event System.Threading.ParameterizedThreadStart PublicEventField;
public IDisposable Prop { get; set; }
public Exception this[ArgumentException t] { get { return t; } }
}
}
""";
var src2 = """
using System;
using N20 = Mscorlib20;
class Test
{
public IDisposable M()
{
var obj = new N20::CGoo();
N20.IGoo igoo = obj;
/*<bind0>*/obj.PublicEventField/*</bind0>*/ += /*<bind1>*/MyEveHandler/*</bind1>*/;
var local = /*<bind2>*/igoo[null]/*</bind2>*/;
if (/*<bind3>*/obj.PublicField /*</bind3>*/== DayOfWeek.Friday)
{
return /*<bind4>*/(obj as N20.IGoo).Prop/*</bind4>*/;
}
return null;
}
public void MyEveHandler(object o) { }
}
""";
var comp20 = CreateEmptyCompilation(src1, [Net40.References.mscorlib]);
// "Compilation ref Compilation"
var comp40 = CreateCompilation(src2, [new CSharpCompilationReference(comp20)]);
var originals = GetSourceSymbols(comp20, SymbolCategory.NonTypeMember | SymbolCategory.Parameter);
var originalSymbols = originals.Where(s => !s.IsAccessor() && s.Kind != SymbolKind.Parameter).OrderBy(s => s.Name).ToList();
// IGoo.Prop, CGoo.Prop, Event, Field, IGoo.This, CGoo.This
Assert.Equal(6, originalSymbols.Count);
// ====================
var bindingtuples = GetBindingNodesAndModel<ExpressionSyntax>(comp40);
var model = bindingtuples.Item2;
var list = bindingtuples.Item1;
Assert.Equal(5, list.Count);
// PublicEventField
ResolveAndVerifySymbol(list[0], originalSymbols[2], model, comp20);
// delegate ParameterizedThreadStart
ResolveAndVerifyTypeSymbol(list[0], (originalSymbols[2] as IEventSymbol).Type, model, comp20);
// MethodGroup
ResolveAndVerifyTypeSymbol(list[1], (originalSymbols[2] as IEventSymbol).Type, model, comp20);
// Indexer
ResolveAndVerifySymbol(list[2], originalSymbols[4], model, comp20);
// class Exception
ResolveAndVerifyTypeSymbol(list[2], (originalSymbols[4] as IPropertySymbol).Type, model, comp20);
// PublicField
ResolveAndVerifySymbol(list[3], originalSymbols[3], model, comp20);
// enum DayOfWeek
ResolveAndVerifyTypeSymbol(list[3], (originalSymbols[3] as IFieldSymbol).Type, model, comp20);
// Prop
ResolveAndVerifySymbol(list[4], originalSymbols[0], model, comp20);
// interface IDisposable
ResolveAndVerifyTypeSymbol(list[4], (originalSymbols[0] as IPropertySymbol).Type, model, comp20);
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546255")]
public void M2MMultiTargetingMsCorLib03()
{
var src1 = """
using System;
namespace Mscorlib20
{
public interface IGoo
{
// interface
IDisposable Prop { get; set; }
// class
Exception this[ArgumentException t] { get; }
}
public class CGoo : IGoo
{
// explicit
IDisposable IGoo.Prop { get; set; }
Exception IGoo.this[ArgumentException t] { get { return t; } }
}
}
""";
var src2 = """
using System;
using N20 = Mscorlib20;
class Test
{
public IDisposable M()
{
N20.IGoo igoo = new N20::CGoo();
var local = /*<bind0>*/igoo[new ArgumentException()]/*</bind0>*/;
return /*<bind1>*/igoo.Prop/*</bind1>*/;
}
}
""";
var comp20 = CreateEmptyCompilation(src1, [Net40.References.mscorlib]);
// "Compilation ref Compilation"
var comp40 = CreateCompilation(src2, [new CSharpCompilationReference(comp20)]);
var originals = GetSourceSymbols(comp20, SymbolCategory.NonTypeMember | SymbolCategory.Parameter);
var originalSymbols = originals.Where(s => !s.IsAccessor() && s.Kind != SymbolKind.Parameter).OrderBy(s => s.Name).ToList();
// CGoo.Prop, CGoo.This, IGoo.Prop, IGoo.This
Assert.Equal(4, originalSymbols.Count);
// ====================
var bindingtuples = GetBindingNodesAndModel<ExpressionSyntax>(comp40);
var model = bindingtuples.Item2;
var list = bindingtuples.Item1;
Assert.Equal(2, list.Count);
// Indexer
ResolveAndVerifySymbol(list[0], originalSymbols[3], model, comp20);
// class Exception
ResolveAndVerifyTypeSymbol(list[0], (originalSymbols[3] as IPropertySymbol).Type, model, comp20);
// Prop
ResolveAndVerifySymbol(list[1], originalSymbols[2], model, comp20);
// interface IDisposable
ResolveAndVerifyTypeSymbol(list[1], (originalSymbols[2] as IPropertySymbol).Type, model, comp20);
}
#endregion
}
|