/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/CoreTest/UtilityTest/DocumentationCommentIdTests.cs
354 строки
15 KB
Cyrus Najmabadi
Use raw strings in tests
09 июл 2025, 08:52
09 июл 2025, 08:52
f265dce
Код
Авторство
О чём код?
// 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.Linq; using Microsoft.CodeAnalysis.CSharp; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.UnitTests; public sealed partial class DocumentationCommentIdTests : TestBase { private static CSharpCompilation CreateCSharpCompilation(string sourceText) { var syntaxTree = SyntaxFactory.ParseSyntaxTree(sourceText); return CSharpCompilation.Create("goo.exe").AddReferences(NetFramework.mscorlib).AddSyntaxTrees(syntaxTree); } private static void CheckDeclarationId(string expectedId, INamespaceOrTypeSymbol symbol, Compilation compilation) { var id = DocumentationCommentId.CreateDeclarationId(symbol); Assert.Equal(expectedId, id); var sym = DocumentationCommentId.GetFirstSymbolForDeclarationId(id, compilation); Assert.Equal(symbol, sym); } private static TSymbol CheckDeclarationId<TSymbol>(string expectedId, Compilation compilation, Func<TSymbol, bool> test) where TSymbol : ISymbol { var symbol = DocumentationCommentId.GetFirstSymbolForDeclarationId(expectedId, compilation); Assert.True(symbol is TSymbol); Assert.True(test((TSymbol)symbol)); return (TSymbol)symbol; } private static void CheckDeclarationIdExact<TSymbol>(string expectedId, Compilation compilation, Func<TSymbol, bool> test) where TSymbol : ISymbol { var symbol = CheckDeclarationId(expectedId, compilation, test); var id = DocumentationCommentId.CreateDeclarationId(symbol); Assert.Equal(expectedId, id); } private static void CheckReferenceId(string expectedId, INamespaceOrTypeSymbol symbol, Compilation compilation) { var id = DocumentationCommentId.CreateReferenceId(symbol); Assert.Equal(expectedId, id); var sym = DocumentationCommentId.GetSymbolsForReferenceId(id, compilation).FirstOrDefault(); Assert.Equal(symbol, sym); } [Fact] public void TestCSharpTypeIds() { var compilation = CreateCSharpCompilation(""" enum Color { Red, Blue, Green } namespace Acme { interface IProcess { } struct ValueType { private int total; } class Widget : IProcess { public class NestedClass { } public interface IMenuItem { } public delegate void Del(int i); public enum Direction { North, South, East, West } } class MyList<T> { class Helper<U,V> { } } } """); CheckDeclarationId("T:Color", compilation.GetTypeByMetadataName("Color"), compilation); CheckDeclarationId("T:Acme.IProcess", compilation.GetTypeByMetadataName("Acme.IProcess"), compilation); CheckDeclarationId("T:Acme.ValueType", compilation.GetTypeByMetadataName("Acme.ValueType"), compilation); CheckDeclarationId("T:Acme.Widget", compilation.GetTypeByMetadataName("Acme.Widget"), compilation); CheckDeclarationId("T:Acme.Widget.NestedClass", compilation.GetTypeByMetadataName("Acme.Widget+NestedClass"), compilation); CheckDeclarationId("T:Acme.Widget.IMenuItem", compilation.GetTypeByMetadataName("Acme.Widget+IMenuItem"), compilation); CheckDeclarationId("T:Acme.Widget.Del", compilation.GetTypeByMetadataName("Acme.Widget+Del"), compilation); CheckDeclarationId("T:Acme.Widget.Direction", compilation.GetTypeByMetadataName("Acme.Widget+Direction"), compilation); CheckDeclarationId("T:Acme.MyList`1", compilation.GetTypeByMetadataName("Acme.MyList`1"), compilation); CheckDeclarationId("T:Acme.MyList`1.Helper`2", compilation.GetTypeByMetadataName("Acme.MyList`1+Helper`2"), compilation); } [Fact] public void TestCSharpFields() { var compilation = CreateCSharpCompilation(""" enum Color { Red, Blue, Green } namespace Acme { interface IProcess { } struct ValueType { private int total; } class Widget : IProcess { public class NestedClass { private int value; } private string message; private static Color defaultColor; private const double PI = 3.14159; protected readonly double monthlyAverage; private long[] array1; private widget[,] array2; private unsafe int *pCount; private unsafe float **ppValues; } } """); CheckDeclarationId<IFieldSymbol>("F:Acme.ValueType.total", compilation, s => s.Name == "total"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.NestedClass.value", compilation, s => s.Name == "value"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.message", compilation, s => s.Name == "message"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.defaultColor", compilation, s => s.Name == "defaultColor"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.PI", compilation, s => s.Name == "PI"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.monthlyAverage", compilation, s => s.Name == "monthlyAverage"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.array1", compilation, s => s.Name == "array1"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.array2", compilation, s => s.Name == "array2"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.pCount", compilation, s => s.Name == "pCount"); CheckDeclarationId<IFieldSymbol>("F:Acme.Widget.ppValues", compilation, s => s.Name == "ppValues"); } [Fact] public void TestCSharpConstructors() { var compilation = CreateCSharpCompilation(""" namespace Acme { interface IProcess { } class Widget : IProcess { static Widget() { } public Widget() { } public Widget(string s) { } } } """); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.#cctor", compilation, s => s.MethodKind == MethodKind.StaticConstructor); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.#ctor", compilation, s => s.MethodKind == MethodKind.Constructor && s.Parameters.Length == 0); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.#ctor(System.String)", compilation, s => s.MethodKind == MethodKind.Constructor && s.Parameters.Length == 1); } [Fact] public void TestCSharpDestructors() { var compilation = CreateCSharpCompilation(""" namespace Acme { interface IProcess { } class Widget : IProcess { ~Widget() { } } } """); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.Finalize", compilation, s => s.MethodKind == MethodKind.Destructor); } [Fact] public void TestCSharpMethods() { var compilation = CreateCSharpCompilation(""" enum Color { Red, Blue, Green } namespace Acme { struct ValueType { public void M(int i) { } } interface IProcess { } class Widget : IProcess { public class NestedClass { public void M(int i) { } } public static void M0() { } public void M1(char c, out float f, ref ValueType v) { } public void M2(short[] x1, int[,] x2, long[][] x3) { } public void M3(long[][] x3, Widget[][,,] x4) { } public void M4(char *pc, Color **pf) { } public void M5(void *pv, double *[][,] pd) { } public void M6(int i, params object[] args) { } } class MyList<T> { public void Test(T t) { } } class UseList { public void Process(MyList<int> list) { } public MyList<T> GetValues<T>(T inputValue) { return null; } public void Process2<T>(MyList<T> list) { } } } """); CheckDeclarationId<IMethodSymbol>("M:Acme.ValueType.M(System.Int32)", compilation, s => s.Name == "M" && s.Parameters is [{ Type.Name: "Int32" }]); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.NestedClass.M(System.Int32)", compilation, s => s.Name == "M" && s.Parameters is [{ Type.Name: "Int32" }]); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M0", compilation, s => s.Name == "M0" && s.Parameters.Length == 0); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M1(System.Char,System.Single@,Acme.ValueType@)", compilation, s => s.Name == "M1"); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M2(System.Int16[],System.Int32[0:,0:],System.Int64[][])", compilation, s => s.Name == "M2"); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M3(System.Int64[][],Acme.Widget[0:,0:,0:][])", compilation, s => s.Name == "M3"); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M4(System.Char*,Color**)", compilation, s => s.Name == "M4"); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M5(System.Void*,System.Double*[0:,0:][])", compilation, s => s.Name == "M5"); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.M6(System.Int32,System.Object[])", compilation, s => s.Name == "M6"); CheckDeclarationId<IMethodSymbol>("M:Acme.MyList`1.Test(`0)", compilation, s => s.Name == "Test"); CheckDeclarationId<IMethodSymbol>("M:Acme.UseList.Process(Acme.MyList{System.Int32})", compilation, s => s.Name == "Process"); CheckDeclarationId<IMethodSymbol>("M:Acme.UseList.GetValues``1(``0)", compilation, s => s.Name == "GetValues"); CheckDeclarationId<IMethodSymbol>("M:Acme.UseList.Process2``1(Acme.MyList{``0})", compilation, s => s.Name == "Process2"); } [Fact] public void TestCSharpPropertiesAndIndexers() { var compilation = CreateCSharpCompilation(""" namespace Acme { interface IProcess { } class Widget : IProcess { public int Width { get { return 0; } set { } } public int this[int i] { get { return 0; } set { } } public int this[string s, int i] { get { return 0; } set { } } } } """); CheckDeclarationIdExact<IPropertySymbol>("P:Acme.Widget.Width", compilation, p => p.Name == "Width"); CheckDeclarationIdExact<IPropertySymbol>("P:Acme.Widget.Item(System.Int32)", compilation, p => p.Parameters.Length == 1); CheckDeclarationIdExact<IPropertySymbol>("P:Acme.Widget.Item(System.String,System.Int32)", compilation, p => p.Parameters.Length == 2); } [Fact] public void TestCSharpEvents() { var compilation = CreateCSharpCompilation(""" namespace Acme { class Widget : IProcess { public delegate void Del(int i); public event Del AnEvent; } } """); CheckDeclarationId<IEventSymbol>("E:Acme.Widget.AnEvent", compilation, e => e.Name == "AnEvent"); } [Fact] public void TestCSharpUnaryOperators() { var compilation = CreateCSharpCompilation(""" namespace Acme { class Widget : IProcess { public static Widget operator+(Widget x) { return x; } } } """); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.op_UnaryPlus(Acme.Widget)", compilation, m => m.MethodKind == MethodKind.UserDefinedOperator && m.Parameters.Length == 1); } [Fact] public void TestCSharpBinaryOperators() { var compilation = CreateCSharpCompilation(""" namespace Acme { class Widget : IProcess { public static Widget operator+(Widget x1, Widget x2) { return x1; } } } """); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)", compilation, m => m.MethodKind == MethodKind.UserDefinedOperator && m.Parameters.Length == 2); } [Fact] public void TestCSharpConversionOperators() { var compilation = CreateCSharpCompilation(""" namespace Acme { class Widget : IProcess { public static explicit operator int(Widget x) { return 0; } public static implicit operator long(Widget x) { return 0; } } } """); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int32", compilation, m => m.MethodKind == MethodKind.Conversion && m.Parameters.Length == 1 && m.ReturnType.Name == "Int32"); CheckDeclarationId<IMethodSymbol>("M:Acme.Widget.op_Implicit(Acme.Widget)~System.Int64", compilation, m => m.MethodKind == MethodKind.Conversion && m.Parameters.Length == 1 && m.ReturnType.Name == "Int64"); } [Fact] public void TestTypeReferences() { var compilation = CreateCSharpCompilation(""" namespace Acme { class OuterType<A> { class InnerType<B, C> { } public void M<D>(D d) { } } } """); var outerType = compilation.GetTypeByMetadataName("Acme.OuterType`1"); var innerType = compilation.GetTypeByMetadataName("Acme.OuterType`1+InnerType`2"); var method = outerType.GetMembers("M").First() as IMethodSymbol; var ienum = compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1"); var ienumTP = ienum.Construct(outerType.TypeArguments[0]); var intType = compilation.GetSpecialType(SpecialType.System_Int32); // reference to type parameters CheckReferenceId("T:Acme.OuterType`1:`0", outerType.TypeParameters[0], compilation); CheckReferenceId("T:Acme.OuterType`1.InnerType`2:`1", innerType.TypeParameters[0], compilation); CheckReferenceId("T:Acme.OuterType`1.InnerType`2:`2", innerType.TypeParameters[1], compilation); CheckReferenceId("M:Acme.OuterType`1.M``1(``0):``0", method.TypeParameters[0], compilation); CheckReferenceId("System.Collections.Generic.IEnumerable{T:Acme.OuterType`1:`0}", ienumTP, compilation); // simple types CheckReferenceId("System.Int32", intType, compilation); CheckReferenceId("System.Int32[]", compilation.CreateArrayTypeSymbol(intType), compilation); CheckReferenceId("System.Int32*", compilation.CreatePointerTypeSymbol(intType), compilation); } }