/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/CSharpTest/Debugging/NameResolverTests.cs
639 строк
20 KB
Cyrus Najmabadi
Make sealed
26 мар 2025, 22:21
26 мар 2025, 22:21
d99b771
Код
Авторство
О чём код?
// 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 System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Debugging; using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Debugging; [UseExportProvider] [Trait(Traits.Feature, Traits.Features.DebuggingNameResolver)] public sealed class NameResolverTests { private static async Task TestAsync(string text, string searchText, params string[] expectedNames) { using var workspace = EditorTestWorkspace.CreateCSharp(text); var nameResolver = new BreakpointResolver(workspace.CurrentSolution, searchText); var results = await nameResolver.DoAsync(CancellationToken.None); Assert.Equal(expectedNames, results.Select(r => r.LocationNameOpt)); } [Fact] public async Task TestCSharpLanguageDebugInfoCreateNameResolver() { using var workspace = EditorTestWorkspace.CreateCSharp(" "); var debugInfo = new CSharpBreakpointResolutionService(); var results = await debugInfo.ResolveBreakpointsAsync(workspace.CurrentSolution, "goo", CancellationToken.None); Assert.Equal(0, results.Count()); } [Fact] public async Task TestSimpleNameInClass() { var text = """ class C { void Goo() { } } """; await TestAsync(text, "Goo", "C.Goo()"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "C.Goo()"); await TestAsync(text, "N.C.Goo"); await TestAsync(text, "Goo<T>"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "Goo()", "C.Goo()"); await TestAsync(text, "Goo(int i)"); await TestAsync(text, "Goo(int)"); } [Fact] public async Task TestSimpleNameInNamespace() { var text = """ namespace N { class C { void Goo() { } } } """; await TestAsync(text, "Goo", "N.C.Goo()"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "N.C.Goo()"); await TestAsync(text, "N.C.Goo", "N.C.Goo()"); await TestAsync(text, "Goo<T>"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "Goo()", "N.C.Goo()"); await TestAsync(text, "C.Goo()", "N.C.Goo()"); await TestAsync(text, "N.C.Goo()", "N.C.Goo()"); await TestAsync(text, "Goo(int i)"); await TestAsync(text, "Goo(int)"); await TestAsync(text, "Goo(a)"); } [Fact] public async Task TestSimpleNameInGenericClassNamespace() { var text = """ namespace N { class C<T> { void Goo() { } } } """; await TestAsync(text, "Goo", "N.C<T>.Goo()"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "N.C<T>.Goo()"); await TestAsync(text, "N.C.Goo", "N.C<T>.Goo()"); await TestAsync(text, "Goo<T>"); await TestAsync(text, "C<T>.Goo", "N.C<T>.Goo()"); await TestAsync(text, "C<T>.Goo()", "N.C<T>.Goo()"); await TestAsync(text, "Goo()", "N.C<T>.Goo()"); await TestAsync(text, "C.Goo()", "N.C<T>.Goo()"); await TestAsync(text, "N.C.Goo()", "N.C<T>.Goo()"); await TestAsync(text, "Goo(int i)"); await TestAsync(text, "Goo(int)"); await TestAsync(text, "Goo(a)"); } [Fact] public async Task TestGenericNameInClassNamespace() { var text = """ namespace N { class C { void Goo<T>() { } } } """; await TestAsync(text, "Goo", "N.C.Goo<T>()"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "N.C.Goo<T>()"); await TestAsync(text, "N.C.Goo", "N.C.Goo<T>()"); await TestAsync(text, "Goo<T>", "N.C.Goo<T>()"); await TestAsync(text, "Goo<X>", "N.C.Goo<T>()"); await TestAsync(text, "Goo<T,X>"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "C<T>.Goo()"); await TestAsync(text, "Goo()", "N.C.Goo<T>()"); await TestAsync(text, "C.Goo()", "N.C.Goo<T>()"); await TestAsync(text, "N.C.Goo()", "N.C.Goo<T>()"); await TestAsync(text, "Goo(int i)"); await TestAsync(text, "Goo(int)"); await TestAsync(text, "Goo(a)"); await TestAsync(text, "Goo<T>(int i)"); await TestAsync(text, "Goo<T>(int)"); await TestAsync(text, "Goo<T>(a)"); } [Fact] public async Task TestOverloadsInSingleClass() { var text = """ class C { void Goo() { } void Goo(int i) { } } """; await TestAsync(text, "Goo", "C.Goo()", "C.Goo(int)"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "C.Goo()", "C.Goo(int)"); await TestAsync(text, "N.C.Goo"); await TestAsync(text, "Goo<T>"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "Goo()", "C.Goo()"); await TestAsync(text, "Goo(int i)", "C.Goo(int)"); await TestAsync(text, "Goo(int)", "C.Goo(int)"); await TestAsync(text, "Goo(i)", "C.Goo(int)"); } [Fact] public async Task TestMethodsInMultipleClasses() { var text = """ namespace N { class C { void Goo() { } } } namespace N1 { class C { void Goo(int i) { } } } """; await TestAsync(text, "Goo", "N1.C.Goo(int)", "N.C.Goo()"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "N1.C.Goo(int)", "N.C.Goo()"); await TestAsync(text, "N.C.Goo", "N.C.Goo()"); await TestAsync(text, "N1.C.Goo", "N1.C.Goo(int)"); await TestAsync(text, "Goo<T>"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "Goo()", "N.C.Goo()"); await TestAsync(text, "Goo(int i)", "N1.C.Goo(int)"); await TestAsync(text, "Goo(int)", "N1.C.Goo(int)"); await TestAsync(text, "Goo(i)", "N1.C.Goo(int)"); } [Fact] public async Task TestMethodsWithDifferentArityInMultipleClasses() { var text = """ namespace N { class C { void Goo() { } } } namespace N1 { class C { void Goo<T>(int i) { } } } """; await TestAsync(text, "Goo", "N1.C.Goo<T>(int)", "N.C.Goo()"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "N1.C.Goo<T>(int)", "N.C.Goo()"); await TestAsync(text, "N.C.Goo", "N.C.Goo()"); await TestAsync(text, "N1.C.Goo", "N1.C.Goo<T>(int)"); await TestAsync(text, "Goo<T>", "N1.C.Goo<T>(int)"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "Goo()", "N.C.Goo()"); await TestAsync(text, "Goo<T>()"); await TestAsync(text, "Goo(int i)", "N1.C.Goo<T>(int)"); await TestAsync(text, "Goo(int)", "N1.C.Goo<T>(int)"); await TestAsync(text, "Goo(i)", "N1.C.Goo<T>(int)"); await TestAsync(text, "Goo<T>(int i)", "N1.C.Goo<T>(int)"); await TestAsync(text, "Goo<T>(int)", "N1.C.Goo<T>(int)"); await TestAsync(text, "Goo<T>(i)", "N1.C.Goo<T>(int)"); } [Fact] public async Task TestOverloadsWithMultipleParametersInSingleClass() { var text = """ class C { void Goo(int a) { } void Goo(int a, string b = "bb") { } void Goo(__arglist) { } } """; await TestAsync(text, "Goo", "C.Goo(int)", "C.Goo(int, [string])", "C.Goo(__arglist)"); await TestAsync(text, "goo"); await TestAsync(text, "C.Goo", "C.Goo(int)", "C.Goo(int, [string])", "C.Goo(__arglist)"); await TestAsync(text, "N.C.Goo"); await TestAsync(text, "Goo<T>"); await TestAsync(text, "C<T>.Goo"); await TestAsync(text, "Goo()", "C.Goo(__arglist)"); await TestAsync(text, "Goo(int i)", "C.Goo(int)"); await TestAsync(text, "Goo(int)", "C.Goo(int)"); await TestAsync(text, "Goo(int x = 42)", "C.Goo(int)"); await TestAsync(text, "Goo(i)", "C.Goo(int)"); await TestAsync(text, "Goo(int i, int b)", "C.Goo(int, [string])"); await TestAsync(text, "Goo(int, bool)", "C.Goo(int, [string])"); await TestAsync(text, "Goo(i, s)", "C.Goo(int, [string])"); await TestAsync(text, "Goo(,)", "C.Goo(int, [string])"); await TestAsync(text, "Goo(int x = 42,)", "C.Goo(int, [string])"); await TestAsync(text, "Goo(int x = 42, y = 42)", "C.Goo(int, [string])"); await TestAsync(text, "Goo([attr] x = 42, y = 42)", "C.Goo(int, [string])"); await TestAsync(text, "Goo(int i, int b, char c)"); await TestAsync(text, "Goo(int, bool, char)"); await TestAsync(text, "Goo(i, s, c)"); await TestAsync(text, "Goo(__arglist)", "C.Goo(int)"); } [Fact] public async Task AccessorTests() { var text = """ class C { int Property1 { get { return 42; } } int Property2 { set { } } int Property3 { get; set;} } """; await TestAsync(text, "Property1", "C.Property1"); await TestAsync(text, "Property2", "C.Property2"); await TestAsync(text, "Property3", "C.Property3"); } [Fact] public async Task NegativeTests() { var text = """ using System.Runtime.CompilerServices; abstract class C { public abstract void AbstractMethod(int a); int Field; delegate void Delegate(); event Delegate Event; [IndexerName("ABCD")] int this[int i] { get { return i; } } void Goo() { } void Goo(int x = 1, int y = 2) { } ~C() { } } """; await TestAsync(text, "AbstractMethod"); await TestAsync(text, "Field"); await TestAsync(text, "Delegate"); await TestAsync(text, "Event"); await TestAsync(text, "this"); await TestAsync(text, "C.this[int]"); await TestAsync(text, "C.get_Item"); await TestAsync(text, "C.get_Item(i)"); await TestAsync(text, "C[i]"); await TestAsync(text, "ABCD"); await TestAsync(text, "C.ABCD(int)"); await TestAsync(text, "42"); await TestAsync(text, "Goo", "C.Goo()", "C.Goo([int], [int])"); // just making sure it would normally resolve before trying bad syntax await TestAsync(text, "Goo Goo"); await TestAsync(text, "Goo()asdf"); await TestAsync(text, "Goo(),"); await TestAsync(text, "Goo(),f"); await TestAsync(text, "Goo().Goo"); await TestAsync(text, "Goo("); await TestAsync(text, "(Goo"); await TestAsync(text, "Goo)"); await TestAsync(text, "(Goo)"); await TestAsync(text, "Goo(x = 42, y = 42)", "C.Goo([int], [int])"); // just making sure it would normally resolve before trying bad syntax await TestAsync(text, "int x = 42"); await TestAsync(text, "Goo(int x = 42, y = 42"); await TestAsync(text, "C"); await TestAsync(text, "C.C"); await TestAsync(text, "~"); await TestAsync(text, "~C"); await TestAsync(text, "C.~C()"); await TestAsync(text, ""); } [Fact] public async Task TestInstanceConstructors() { var text = """ class C { public C() { } } class G<T> { public G() { } ~G() { } } """; await TestAsync(text, "C", "C.C()"); await TestAsync(text, "C.C", "C.C()"); await TestAsync(text, "C.C()", "C.C()"); await TestAsync(text, "C()", "C.C()"); await TestAsync(text, "C<T>"); await TestAsync(text, "C<T>()"); await TestAsync(text, "C(int i)"); await TestAsync(text, "C(int)"); await TestAsync(text, "C(i)"); await TestAsync(text, "G", "G<T>.G()"); await TestAsync(text, "G()", "G<T>.G()"); await TestAsync(text, "G.G", "G<T>.G()"); await TestAsync(text, "G.G()", "G<T>.G()"); await TestAsync(text, "G<T>.G", "G<T>.G()"); await TestAsync(text, "G<t>.G()", "G<T>.G()"); await TestAsync(text, "G<T>"); await TestAsync(text, "G<T>()"); await TestAsync(text, "G.G<T>"); await TestAsync(text, ".ctor"); await TestAsync(text, ".ctor()"); await TestAsync(text, "C.ctor"); await TestAsync(text, "C.ctor()"); await TestAsync(text, "G.ctor"); await TestAsync(text, "G<T>.ctor()"); await TestAsync(text, "Finalize", "G<T>.~G()"); } [Fact] public async Task TestStaticConstructors() { var text = """ class C { static C() { } } """; await TestAsync(text, "C", "C.C()"); await TestAsync(text, "C.C", "C.C()"); await TestAsync(text, "C.C()", "C.C()"); await TestAsync(text, "C()", "C.C()"); await TestAsync(text, "C<T>"); await TestAsync(text, "C<T>()"); await TestAsync(text, "C(int i)"); await TestAsync(text, "C(int)"); await TestAsync(text, "C(i)"); await TestAsync(text, "C.cctor"); await TestAsync(text, "C.cctor()"); } [Fact] public async Task TestAllConstructors() { var text = """ class C { static C() { } public C(int i) { } } """; await TestAsync(text, "C", "C.C(int)", "C.C()"); await TestAsync(text, "C.C", "C.C(int)", "C.C()"); await TestAsync(text, "C.C()", "C.C()"); await TestAsync(text, "C()", "C.C()"); await TestAsync(text, "C<T>"); await TestAsync(text, "C<T>()"); await TestAsync(text, "C(int i)", "C.C(int)"); await TestAsync(text, "C(int)", "C.C(int)"); await TestAsync(text, "C(i)", "C.C(int)"); } [Fact] public async Task TestPartialMethods() { var text = """ partial class C { partial int M1(); partial void M2() { } partial void M2(); partial int M3(); partial int M3(int x) { return 0; } partial void M4() { } } """; await TestAsync(text, "M1"); await TestAsync(text, "C.M1"); await TestAsync(text, "M2", "C.M2()"); await TestAsync(text, "M3", "C.M3(int)"); await TestAsync(text, "M3()"); await TestAsync(text, "M3(y)", "C.M3(int)"); await TestAsync(text, "M4", "C.M4()"); } [Fact] public async Task TestLeadingAndTrailingText() { var text = """ class C { void Goo() { }; } """; await TestAsync(text, "Goo;", "C.Goo()"); await TestAsync(text, @"Goo();", "C.Goo()"); await TestAsync(text, " Goo;", "C.Goo()"); await TestAsync(text, " Goo;;"); await TestAsync(text, " Goo; ;"); await TestAsync(text, @"Goo();", "C.Goo()"); await TestAsync(text, @"Goo();", "C.Goo()"); await TestAsync(text, @"Goo(); // comment", "C.Goo()"); await TestAsync(text, """ /*comment*/ Goo(/* params */); /* comment """, "C.Goo()"); } [Fact] public async Task TestEscapedKeywords() { var text = """ struct @true { } class @foreach { void where(@true @this) { } void @false() { } } """; await TestAsync(text, "where", "@foreach.where(@true)"); await TestAsync(text, "@where", "@foreach.where(@true)"); await TestAsync(text, "@foreach.where", "@foreach.where(@true)"); await TestAsync(text, "foreach.where"); await TestAsync(text, "@foreach.where(true)"); await TestAsync(text, "@foreach.where(@if)", "@foreach.where(@true)"); await TestAsync(text, "false"); } [Fact] public async Task TestAliasQualifiedNames() { var text = """ extern alias A class C { void Goo(D d) { } } """; await TestAsync(text, "A::Goo"); await TestAsync(text, "A::Goo(A::B)"); await TestAsync(text, "A::Goo(A::B)"); await TestAsync(text, "A::C.Goo"); await TestAsync(text, "C.Goo(A::Q)", "C.Goo(D)"); } [Fact] public async Task TestNestedTypesAndNamespaces() { var text = """ namespace N1 { class C { void Goo() { } } namespace N2 { class C { } } namespace N3 { class D { } } namespace N4 { class C { void Goo(double x) { } class D { void Goo() { } class E { void Goo() { } } } } } namespace N5 { } } """; await TestAsync(text, "Goo", "N1.N4.C.Goo(double)", "N1.N4.C.D.Goo()", "N1.N4.C.D.E.Goo()", "N1.C.Goo()"); await TestAsync(text, "C.Goo", "N1.N4.C.Goo(double)", "N1.C.Goo()"); await TestAsync(text, "D.Goo", "N1.N4.C.D.Goo()"); await TestAsync(text, "N1.N4.C.D.Goo", "N1.N4.C.D.Goo()"); await TestAsync(text, "N1.Goo"); await TestAsync(text, "N3.C.Goo"); await TestAsync(text, "N5.C.Goo"); } [Fact] public async Task TestInterfaces() { var text = """ interface I1 { void Goo(); } class C1 : I1 { void I1.Goo() { } } """; await TestAsync(text, "Goo", "C1.Goo()"); await TestAsync(text, "I1.Goo"); await TestAsync(text, "C1.Goo", "C1.Goo()"); await TestAsync(text, "C1.I1.Moo"); } }